diff --git a/AUTHORS b/AUTHORS index 9873d58..e5076c3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,6 +3,5 @@ The DOSBox Team Sjoerd v.d. Berg Peter Veenstra - - - +Felix Jakschitsch +Ulf Wohlers diff --git a/ChangeLog b/ChangeLog index 051d4d6..b7862d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ - 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. + - changed the basedir routines to use the current working dir instead of argv[0]. This will fix and brake things :) + - illegal command, now displays the command + - wildcmp updated to be case insensitive + - added fcb:open,close,findfirst, findnext. + - fixed rename in drive_local + - added new features to the debugger: breakpoint support / data view / command line + - partial support of list of lists (dos info block) + - full emm 3.2 support + - partial emm 4.0 support + - fixes to graphics core fonts (text in sierra games is now correct) + - improved support for user mousehandlers + - fixed EGA graphics + - fixed VGA graphics + - fixed write with size 0 + - changed memory management. + - fixed and cleaned up the cpu flags. + - changed interrupt handler. + - speeded up the graphics. + - speeded up the cpu-core + - changed dma + - improved dma streams from emm memory + - added some cga videomodes + - added more funtions to the keyboard handler diff --git a/NEWS b/NEWS index ba304e2..517fb04 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,26 @@ +0.55: + - changed basedir handling. (linux/winXP) + - added some FCB-calls + - improved support for user mousehandlers + - fixed EGA graphics + - fixed VGA graphics + - fixed the displaying of text in some graphics modes + - fixed write with size 0 + - changed memory management. + - added full emm 3.2 support. + - fixed and cleaned up the cpu flags. + changed interrupt handler. + - speeded up the graphics. + - speeded up the cpu-core + - added new features to the debugger: breakpoint support / data view / command line + - partial support of list of lists (dos info block) + - partial emm 4.0 support + - fixes to graphics core fonts (text in sierra games is now correct) + - changed dma + - improved dma streams from emm memory + - added some cga videomodes + - added more funtions to the keyboard handler + 0.50: -added F3 to repeat the last typed command. -made it possible to change the shellmessages(dosshell). so diff --git a/README b/README index a3dd79a..b6c20dc 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -DOSBox v0.50 +DOSBox v0.55 Usage: ====== diff --git a/acinclude.m4 b/acinclude.m4 index 28772e8..2491c4e 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -159,3 +159,36 @@ int main (int argc, char *argv[]) AC_SUBST(SDL_LIBS) rm -f conf.sdltest ]) + +AH_TOP([ +/* + * 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. + */ +]) + +AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures]) + +AH_BOTTOM([#define INLINE inline]) + +AH_BOTTOM([#if C_HAS_ATTRIBUTE +#define GCC_ATTRIBUTE(x) __attribute__ ((x)) +#else +#define GCC_ATTRIBUTE(x) /* attribute not supported */ +#endif]) + + + diff --git a/aclocal.m4 b/aclocal.m4 index f04491a..331d899 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -173,6 +173,39 @@ int main (int argc, char *argv[]) rm -f conf.sdltest ]) +AH_TOP([ +/* + * 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. + */ +]) + +AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures]) + +AH_BOTTOM([#define INLINE inline]) + +AH_BOTTOM([#if C_HAS_ATTRIBUTE +#define GCC_ATTRIBUTE(x) __attribute__ ((x)) +#else +#define GCC_ATTRIBUTE(x) /* attribute not supported */ +#endif]) + + + + # Do all the work for Automake. -*- Autoconf -*- # This macro actually does too much some checks are only needed if diff --git a/autogen.sh b/autogen.sh index 1c139b8..8b08a7e 100644 --- a/autogen.sh +++ b/autogen.sh @@ -1,18 +1,17 @@ #!/bin/sh -# -echo "Generating build information using aclocal, auotheader, automake and autoconf" + +echo "Generating build information using aclocal, autoheader, automake and autoconf" echo "This may take a while ..." -# Touch the timestamps on all the files since CVS messes them up -directory=`dirname $0` -touch $directory/configure.in - -# Regenerate configuration files +# Regenerate configuration files. aclocal autoheader automake --gnits --include-deps --add-missing --copy autoconf +#Copy settings.h.cvs to settings.h and that's it, + +directory=`dirname $0` cp $directory/settings.h.cvs $directory/settings.h echo "Now you are ready to run ./configure also check settings.h for extra build settings" diff --git a/config.h.in b/config.h.in index 072298a..ee193ec 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,28 @@ /* config.h.in. Generated from configure.in by autoheader. */ + +/* + * 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. + */ + + +/* Determines if the compilers supports attributes for structures */ +#undef C_HAS_ATTRIBUTE + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -63,3 +86,11 @@ /* Define to `unsigned' if does not define. */ #undef size_t + +#define INLINE inline + +#if C_HAS_ATTRIBUTE +#define GCC_ATTRIBUTE(x) __attribute__ ((x)) +#else +#define GCC_ATTRIBUTE(x) /* attribute not supported */ +#endif diff --git a/configure b/configure index cb5c2b5..0def7ee 100644 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.53a for dosbox 0.50. +# Generated by GNU Autoconf 2.53a for dosbox 0.55. # # 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.50' -PACKAGE_STRING='dosbox 0.50' +PACKAGE_VERSION='0.55' +PACKAGE_STRING='dosbox 0.55' 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.50 to adapt to many kinds of systems. +\`configure' configures dosbox 0.55 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.50:";; + short | recursive ) echo "Configuration of dosbox 0.55:";; 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.50 +dosbox configure 0.55 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.50, which was +It was created by dosbox $as_me 0.55, 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.50 + VERSION=0.55 cat >>confdefs.h <<_ACEOF @@ -4232,9 +4232,52 @@ _ACEOF fi +#Check if the compiler support attributes +echo "$as_me:$LINENO: checking if compiler allows __attribute__" >&5 +echo $ECHO_N "checking if compiler allows __attribute__... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +typedef struct { } __attribute__ ((packed)) junk; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6;cat >>confdefs.h <<\_ACEOF +#define C_HAS_ATTRIBUTE 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.$ac_objext conftest.$ac_ext -#Always include the standard include dir in all makefiless ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_16/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/ints/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile include/Makefile" cat >confcache <<\_ACEOF @@ -4594,7 +4637,7 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by dosbox $as_me 0.50, which was +This file was extended by dosbox $as_me 0.55, which was generated by GNU Autoconf 2.53a. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4656,7 +4699,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -dosbox config.status 0.50 +dosbox config.status 0.55 configured by $0, generated by GNU Autoconf 2.53a, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.in b/configure.in index 395ff76..c0cb967 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Init. -AC_INIT(dosbox,0.50) +AC_INIT(dosbox,0.55) AC_CONFIG_SRCDIR(README) dnl Detect the canonical host and target build environment @@ -36,11 +36,12 @@ AC_C_INLINE AC_TYPE_SIZE_T AC_STRUCT_TM -dnl Checks for library functions. +#Check if the compiler support attributes +AC_MSG_CHECKING(if compiler allows __attribute__) +AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;], + [ AC_MSG_RESULT(yes);AC_DEFINE(C_HAS_ATTRIBUTE)],AC_MSG_RESULT(no)) -#Always include the standard include dir in all makefiless - AC_OUTPUT([ Makefile src/Makefile diff --git a/include/bios.h b/include/bios.h index 9d74b59..61d940b 100644 --- a/include/bios.h +++ b/include/bios.h @@ -39,7 +39,7 @@ /* #define bios_keyboard_buffer (*(unsigned int *) 0x41e) */ #define BIOS_DRIVE_ACTIVE 0x43e #define BIOS_DRIVE_RUNNING 0x43f -#define BIOS_MOTOR_NACHLAUFZEIT 0x440 +#define BIOS_DISK_MOTOR_TIMEOUT 0x440 #define BIOS_DISK_STATUS 0x441 /* #define bios_fdc_result_buffer (*(unsigned short *) 0x442) */ #define BIOS_VIDEO_MODE 0x449 diff --git a/include/cpu.h b/include/cpu.h index 15e67ae..1712713 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -29,12 +29,8 @@ typedef Bitu (CPU_Decoder)(Bitu count); extern CPU_Decoder * cpudecoder; extern Bit32u cpu_cycles; - -extern Bit32u hoever; - //CPU Stuff void SetCPU16bit(); -void SetSegment_16(Bit32u seg,Bit16u val); //Types of Flag changing instructions @@ -80,20 +76,11 @@ bool get_SF(void); bool get_OF(void); bool get_PF(void); -Bit8u get_Flags8(void); - - - - #define LoadCF flags.cf=get_CF(); #define LoadZF flags.zf=get_ZF(); #define LoadSF flags.sf=get_SF(); #define LoadOF flags.of=get_OF(); -//The opcode handlers -void FPU_ESC0_Normal(Bitu rm); -void FPU_ESC0_EA(Bitu func,PhysOff ea); - #endif diff --git a/include/cross.h b/include/cross.h index 20d2d5a..2dc3d2c 100644 --- a/include/cross.h +++ b/include/cross.h @@ -46,7 +46,9 @@ #define CROSS_NONE 0 #define CROSS_FILE 1 #define CROSS_DIR 2 - +#if defined (_MSC_VER) +#define ftruncate(blah,blah2) chsize(blah,blah2) +#endif extern const char * dosbox_datadir; diff --git a/include/debug.h b/include/debug.h index 20deed7..300fa11 100644 --- a/include/debug.h +++ b/include/debug.h @@ -18,6 +18,7 @@ void DEBUG_DrawScreen(void); bool DEBUG_BreakPoint(void); +bool DEBUG_IntBreakpoint(Bit8u intNum); void DEBUG_Enable(void); extern Bitu cycle_count; diff --git a/include/dma.h b/include/dma.h index e6923da..56a271b 100644 --- a/include/dma.h +++ b/include/dma.h @@ -16,9 +16,10 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -void DMA_8_Read(Bit32u channel,Bit8u * buffer,Bit16u count); -void DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); -void DMA_16_Read(Bit32u channel,Bit8u * buffer,Bit16u count); -void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); +Bit16u DMA_8_Read(Bit32u channel,Bit8u * buffer,Bit16u count); +Bit16u DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); + +Bit16u DMA_16_Read(Bit32u channel,Bit8u * buffer,Bit16u count); +Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); diff --git a/include/dos_inc.h b/include/dos_inc.h index 32414ca..5edb717 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -22,12 +22,12 @@ #include #include -#pragma pack(1) +#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 */ @@ -55,7 +55,7 @@ struct PSP { CommandTail cmdtail; -}; +} GCC_ATTRIBUTE(packed); struct ParamBlock { union { @@ -72,7 +72,8 @@ struct ParamBlock { RealPt initcsip; } exec; }; -}; +} GCC_ATTRIBUTE(packed); + struct MCB { Bit8u type; @@ -80,23 +81,9 @@ struct MCB { Bit16u size; Bit8u unused[3]; Bit8u filename[8]; -}; +} GCC_ATTRIBUTE(packed); -struct FCB { - 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 -}; - -#pragma pack() +#pragma pack () struct DOS_Date { Bit16u year; @@ -125,7 +112,6 @@ struct DOS_Block { struct { RealPt indosflag; } tables; - }; enum { MCB_FREE=0x0000,MCB_DOS=0x0008 }; @@ -157,20 +143,21 @@ 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); /* Routines for Drive Class */ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry); bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); bool DOS_UnlinkFile(char * name); bool DOS_FindFirst(char *search,Bit16u attr); bool DOS_FindNext(void); -bool DOS_Canonicalize(char * small,Bit8u * big); +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); bool DOS_SetDrive(Bit8u drive); -bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer); +bool DOS_GetCurrentDir(Bit8u drive,char * bugger); bool DOS_ChangeDir(char * dir); bool DOS_MakeDir(char * dir); bool DOS_RemoveDir(char * dir); @@ -195,6 +182,13 @@ 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_FCBClose(Bit16u seg,Bit16u offset); +bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset); +bool DOS_FCBFindNext(Bit16u seg,Bit16u offset); +Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change); /* Extra DOS Interrupts */ void DOS_SetupMisc(void); @@ -211,8 +205,8 @@ INLINE Bit16u long2para(Bit32u size) { }; INLINE Bit8u RealHandle(Bit16u handle) { - PSP * psp=(PSP *)real_off(dos.psp,0); - if (handle>=psp->max_files) return DOS_FILES; + PSP * psp=(PSP *)HostMake(dos.psp,0); + if (handle>=psp->max_files) return 0xff; return mem_readb(Real2Phys(psp->file_table)+handle); }; @@ -245,7 +239,7 @@ public: off=pt; } DOS_FCB(Bit16u seg, Bit16u offset){ - off=Real2Phys(RealMake(seg,offset)); + off=PhysMake(seg,offset); } void Set_drive(Bit8u a); void Set_filename(char* a); //writes an the first 8 bytes of a as the filename @@ -270,6 +264,54 @@ private: +class DOS_ParamBlock { +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); +private: + PhysPt off; +}; + +class DOS_InfoBlock { +public: + DOS_InfoBlock (void) { seg=0; dib=0; }; + + void SetLocation (Bit16u segment); + void SetFirstMCB (RealPt pt); + void GetDIBPointer (Bit16u& segment, Bit16u& offset); + +private: + #pragma pack (push,1) + struct SDosInfoBlock { + Bit8u stuff1[22]; // some stuff, hopefully never used.... + RealPt firstMCB; // first memory control block + RealPt firstDPB; // first drive parameter block + RealPt firstFileTable; // first system file table + RealPt activeClock; // active clock device header + RealPt activeCon; // active console device header + Bit16u maxSectorLength; // maximum bytes per sector of any block device; + RealPt discInfoBuffer; // pointer to disc info buffer + RealPt curDirStructure; // pointer to current array of directory structure + RealPt fcbTable; // pointer to system FCB table + // some more stuff, hopefully never used. + } GCC_ATTRIBUTE(packed); + #pragma pack (pop) + + SDosInfoBlock* dib; + Bit16u seg; +}; + +extern DOS_InfoBlock dosInfoBlock; #endif diff --git a/include/dos_system.h b/include/dos_system.h index 55f210a..0b240d0 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -35,7 +35,9 @@ enum { DOS_ATTR_ARCHIVE= 0x20 }; -#pragma pack (1) +#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 */ @@ -45,8 +47,13 @@ struct DTA_FindBlock { Bit16u date; Bit32u size; char name[DOS_NAMELENGTH]; -}; -#pragma pack () +} +#if defined (_MSC_VER) +; +#pragma pack() +#else +__attribute__ ((packed)); +#endif class DOS_File { public: @@ -82,6 +89,8 @@ public: 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; char * GetInfo(void); char curdir[DOS_PATHLENGTH]; char info[256]; diff --git a/include/dosbox.h b/include/dosbox.h index 8b7e26c..b277391 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -19,45 +19,43 @@ #if !defined __DOSBOX_H #define __DOSBOX_H -typedef unsigned char Bit8u; -typedef signed char Bit8s; -typedef unsigned short Bit16u; -typedef signed short Bit16s; -typedef unsigned long Bit32u; -typedef signed long Bit32s; + +void E_Exit(char * message,...); + +void S_Warn(char * message,...); + +/* The internal types */ +typedef unsigned char Bit8u; +typedef signed char Bit8s; +typedef unsigned short Bit16u; +typedef signed short Bit16s; +typedef unsigned long Bit32u; +typedef signed long Bit32s; +typedef double Real64; #if defined(_MSC_VER) -typedef unsigned __int64 Bit64u; -typedef signed __int64 Bit64s; +typedef unsigned __int64 Bit64u; +typedef signed __int64 Bit64s; #else -typedef unsigned long long int Bit64u; -typedef signed long long int Bit64s; +typedef unsigned long long Bit64u; +typedef signed long long Bit64s; #endif typedef unsigned int Bitu; typedef signed int Bits; #include - -void E_Exit(char * message,...); - -void S_Warn(char * message,...); - - -#include "../settings.h" /* General extra setting */ -#if defined (_MSC_VER) -#include "../src/platform/visualc/config.h" -#else -#include "../config.h" -#define INLINE inline -#endif - +#include "config.h" +#include "../settings.h" 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); + + #endif diff --git a/include/fpu.h b/include/fpu.h index 8b13789..d181a2a 100644 --- a/include/fpu.h +++ b/include/fpu.h @@ -1 +1,50 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef __FPU_H +#define __FPU_H + +#include "mem.h" + +void FPU_ESC0_Normal(Bitu rm); +void FPU_ESC0_EA(Bitu func,PhysPt ea); +void FPU_ESC1_Normal(Bitu rm); +void FPU_ESC1_EA(Bitu func,PhysPt ea); +void FPU_ESC2_Normal(Bitu rm); +void FPU_ESC2_EA(Bitu func,PhysPt ea); +void FPU_ESC3_Normal(Bitu rm); +void FPU_ESC3_EA(Bitu func,PhysPt ea); +void FPU_ESC4_Normal(Bitu rm); +void FPU_ESC4_EA(Bitu func,PhysPt ea); +void FPU_ESC5_Normal(Bitu rm); +void FPU_ESC5_EA(Bitu func,PhysPt ea); +void FPU_ESC6_Normal(Bitu rm); +void FPU_ESC6_EA(Bitu func,PhysPt ea); +void FPU_ESC7_Normal(Bitu rm); +void FPU_ESC7_EA(Bitu func,PhysPt ea); + +#define FPU_ESC(code) { \ + Bit8u rm=Fetchb(); \ + if (rm>=0xc0) { \ + FPU_ESC ## code ## _Normal(rm); \ + } else { \ + GetEAa;FPU_ESC ## code ## _EA(rm,eaa); \ + } \ +} + +#endif diff --git a/include/mem.h b/include/mem.h index 1fa0856..e891cb4 100644 --- a/include/mem.h +++ b/include/mem.h @@ -20,79 +20,62 @@ #define __MEM_H #include -enum { MEMORY_HANDLER=1,MEMORY_RELOCATE=2}; - #define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size) -typedef Bit8u (MEMORY_ReadHandler)(Bit32u start); -typedef void (MEMORY_WriteHandler)(Bit32u start,Bit8u val); - -typedef Bit32u PhysOff; typedef Bit32u PhysPt; -typedef Bit8u * HostOff; typedef Bit8u * HostPt; typedef Bit32u RealPt; -struct PageEntry { - Bit8u type; - PhysOff base; /* Used to calculate relative offset */ - struct { - MEMORY_WriteHandler * write; - MEMORY_ReadHandler * read; - } handler; - HostOff relocate; /* This points to host machine address */ -}; +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_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) + +extern HostPt ReadHostTable[MAX_PAGES]; +extern HostPt WriteHostTable[MAX_PAGES]; +extern MEMORY_ReadHandler ReadHandlerTable[MAX_PAGES]; +extern MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES]; -struct EMM_Handle { - Bit16u next; - Bit16u size; /* Size in pages */ - PhysOff phys_base; - HostOff host_base; - bool active; - bool free; -}; INLINE Bit16u PAGES(Bit32u bytes) { if ((bytes & 4095) == 0) return (Bit16u)(bytes>>12); return (Bit16u)(1+(bytes>>12)); } -extern Bit8u * memory; -extern EMM_Handle EMM_Handles[]; -extern PageEntry * PageEntries[]; /* Number of pages */ -bool MEMORY_TestSpecial(PhysOff off); -void MEMORY_SetupHandler(Bit32u page,Bit32u extra,PageEntry * handler); -void MEMORY_ResetHandler(Bit32u page,Bit32u pages); +void MEM_SetupPageHandlers(Bitu startpage,Bitu pages,MEMORY_ReadHandler read,MEMORY_WriteHandler write); +void MEM_ClearPageHandlers(Bitu startpage,Bitu pages); +void MEM_SetupMapping(Bitu startpage,Bitu pages,void * data); +void MEM_ClearMapping(Bitu startpage,Bitu pages); -void EMM_GetFree(Bit16u * maxblock,Bit16u * total); -void EMM_Allocate(Bit16u size,Bit16u * handle); -void EMM_Free(Bit16u handle); - +extern HostPt memory; /* The folowing six functions are used everywhere in the end so these should be changed for Working on big or little endian machines */ - -INLINE Bit8u readb(HostOff off) { +INLINE Bit8u readb(HostPt off) { return *(Bit8u *)off; }; -INLINE Bit16u readw(HostOff off) { +INLINE Bit16u readw(HostPt off) { return *(Bit16u *)off; }; -INLINE Bit32u readd(HostOff off) { +INLINE Bit32u readd(HostPt off) { return *(Bit32u *)off; }; -INLINE void writeb(HostOff off,Bit8u val) { +INLINE void writeb(HostPt off,Bit8u val) { *(Bit8u *)(off)=val; }; -INLINE void writew(HostOff off,Bit16u val) { +INLINE void writew(HostPt off,Bit16u val) { *(Bit16u *)(off)=val; }; -INLINE void writed(HostOff off,Bit32u val) { +INLINE void writed(HostPt off,Bit32u val) { *(Bit32u *)(off)=val; }; @@ -100,38 +83,79 @@ INLINE void writed(HostOff off,Bit32u val) { /* The Folowing six functions are slower but they recognize the paged memory system */ //TODO maybe make em inline to go a bit faster -Bit8u mem_readb(PhysOff off); -Bit16u mem_readw(PhysOff off); -Bit32u mem_readd(PhysOff off); +#if (!C_EXTRAINLINE) +Bit8u mem_readb(PhysPt pt); +Bit16u mem_readw(PhysPt pt); +Bit32u mem_readd(PhysPt pt); -void mem_writeb(PhysOff off,Bit8u val); -void mem_writew(PhysOff off,Bit16u val); -void mem_writed(PhysOff off,Bit32u val); +void mem_writeb(PhysPt pt,Bit8u val); +void mem_writew(PhysPt pt,Bit16u val); +void mem_writed(PhysPt pt,Bit32u val); +#else +INLINE void mem_writeb(PhysPt pt,Bit8u val) { + if (WriteHostTable[pt >> PAGE_SHIFT]) writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); + else { + WriteHandlerTable[pt >> PAGE_SHIFT](pt,val); + } +} +INLINE void mem_writew(PhysPt pt,Bit16u val) { + if (WriteHostTable[pt >> PAGE_SHIFT]) writew(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); + else { + WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); + } +} +INLINE void mem_writed(PhysPt pt,Bit32u val) { + if (WriteHostTable[pt >> PAGE_SHIFT]) writed(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); + else { + WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+2,(Bit8u)((val >> 16) & 0xff) ); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+3,(Bit8u)((val >> 24) & 0xff) ); + } +} -void MEM_BlockWrite(PhysOff off,void * data,Bitu size); -void MEM_BlockRead(PhysOff off,void * data,Bitu size); -void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size); -void MEM_StrCopy(PhysOff off,char * data,Bitu size); +INLINE Bit8u mem_readb(PhysPt pt) { + if (ReadHostTable[pt >> PAGE_SHIFT]) return readb(ReadHostTable[pt >> PAGE_SHIFT]+pt); + else { + return ReadHandlerTable[pt >> PAGE_SHIFT](pt); + } +} +INLINE Bit16u mem_readw(PhysPt pt) { + if (ReadHostTable[pt >> PAGE_SHIFT]) return readw(ReadHostTable[pt >> PAGE_SHIFT]+pt); + else { + return + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8; + } +} + +INLINE Bit32u mem_readd(PhysPt pt){ + if (ReadHostTable[pt >> PAGE_SHIFT]) return readd(ReadHostTable[pt >> PAGE_SHIFT]+pt); + else { + return + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8 | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+2)) << 16 | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+3)) << 24; + } +} + +#endif + +void MEM_BlockWrite(PhysPt pt,void * data,Bitu size); +void MEM_BlockRead(PhysPt pt,void * data,Bitu size); +void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size); +void MEM_StrCopy(PhysPt pt,char * data,Bitu size); /* The folowing functions are all shortcuts to the above functions using physical addressing */ -INLINE HostOff real_off(Bit16u seg,Bit32u off) { - return memory+(seg<<4)+off; -}; - -INLINE HostOff real_host(Bit16u seg,Bit32u off) { - return memory+(seg<<4)+off; -}; -INLINE PhysOff real_phys(Bit16u seg,Bit32u off) { - return (seg<<4)+off; -}; - INLINE Bit8u real_readb(Bit16u seg,Bit16u off) { return mem_readb((seg<<4)+off); } @@ -141,9 +165,6 @@ INLINE Bit16u real_readw(Bit16u seg,Bit16u off) { INLINE Bit32u real_readd(Bit16u seg,Bit16u off) { return mem_readd((seg<<4)+off); } -//#define real_readb(seg,off) mem_readb(((seg)<<4)+(off)) -//#define real_readw(seg,off) mem_readw(((seg)<<4)+(off)) -//#define real_readd(seg,off) mem_readd(((seg)<<4)+(off)) INLINE void real_writeb(Bit16u seg,Bit16u off,Bit8u val) { mem_writeb(((seg<<4)+off),val); @@ -155,20 +176,13 @@ INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) { mem_writed(((seg<<4)+off),val); } - -//#define real_writeb(seg,off,val) mem_writeb((((seg)<<4)+(off)),val) -//#define real_writew(seg,off,val) mem_writew((((seg)<<4)+(off)),val) -//#define real_writed(seg,off,val) mem_writed((((seg)<<4)+(off)),val) - -inline Bit32u real_getvec(Bit8u num) { - return real_readd(0,(num<<2)); +INLINE HostPt HostMake(Bit16u seg,Bit16u off) { + return memory+(seg<<4)+off; } -/* -inline void real_setvec(Bit8u num,Bit32u addr) { - real_writed(0,(num<<2),addr); -}; -*/ +INLINE HostPt Phys2Host(PhysPt pt) { + return memory+pt; +} INLINE Bit16u RealSeg(RealPt pt) { return (Bit16u)(pt>>16); @@ -182,17 +196,18 @@ INLINE PhysPt Real2Phys(RealPt pt) { return (RealSeg(pt)<<4) +RealOff(pt); } +INLINE PhysPt PhysMake(Bit16u seg,Bit16u off) { + return (seg<<4)+off; +} INLINE HostPt Real2Host(RealPt pt) { return memory+(RealSeg(pt)<<4) +RealOff(pt); } - INLINE RealPt RealMake(Bit16u seg,Bit16u off) { return (seg<<16)+off; } - INLINE void RealSetVec(Bit8u vec,RealPt pt) { mem_writed(vec<<2,pt); } @@ -201,8 +216,5 @@ INLINE RealPt RealGetVec(Bit8u vec) { return mem_readd(vec<<2); } - - - #endif diff --git a/include/regs.h b/include/regs.h index ec1778e..d4bd3c4 100644 --- a/include/regs.h +++ b/include/regs.h @@ -24,11 +24,8 @@ struct Flag_Info { union { Bit8u b; - Bit8u bs; Bit16u w; - Bit16s ws; Bit32u d; - Bit32s ds; } var1,var2,result; Bitu type; Bitu prev_type; @@ -38,26 +35,13 @@ struct Flag_Info { bool oldcf; }; - - struct Segment { - Bit16u value; - bool special; /* Signal for pointing to special memory */ - HostOff host; /* The address of start in host memory */ - PhysOff phys; /* The phyiscal address start in emulated machine */ + Bit16u val; + PhysPt phys; /* The phyiscal address start in emulated machine */ }; - - -enum { cs=0,ds,es,fs,gs,ss}; - -extern Segment Segs[6]; -extern Flag_Info flags; -//extern Regs regs; - -void SetSegment_16(Bit32u seg,Bit16u val); - +enum SegNames { cs=0,ds,es,fs,gs,ss}; struct CPU_Regs { union { @@ -66,52 +50,83 @@ struct CPU_Regs { struct { Bit8u l,h; }b; - } ax,bx,cx,dx,si,di,sp,bp,ip; + } regs[8],ip; }; +extern Segment Segs[6]; +extern Flag_Info flags; extern CPU_Regs cpu_regs; -#define reg_al cpu_regs.ax.b.l -//extern Bit8u & reg_al=cpu_regs.ax.b.l; +//#define SegPhys(index) Segs[index].phys +//#define SegValue(index) Segs[index].val -#define reg_ah cpu_regs.ax.b.h -#define reg_ax cpu_regs.ax.w -#define reg_eax cpu_regs.ax.d +INLINE PhysPt SegPhys(SegNames index) { + return Segs[index].phys; +} -#define reg_bl cpu_regs.bx.b.l -#define reg_bh cpu_regs.bx.b.h -#define reg_bx cpu_regs.bx.w -#define reg_ebx cpu_regs.bx.d +INLINE Bit16u SegValue(SegNames index) { + return Segs[index].val; +} -#define reg_cl cpu_regs.cx.b.l -#define reg_ch cpu_regs.cx.b.h -#define reg_cx cpu_regs.cx.w -#define reg_ecx cpu_regs.cx.d + +INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) { + return RealMake(SegValue(index),off); +} -#define reg_dl cpu_regs.dx.b.l -#define reg_dh cpu_regs.dx.b.h -#define reg_dx cpu_regs.dx.w -#define reg_edx cpu_regs.dx.d -#define reg_si cpu_regs.si.w -#define reg_esi cpu_regs.si.d +INLINE void SegSet16(Bitu index,Bit16u val) { + Segs[index].val=val; + Segs[index].phys=val << 4; +} -#define reg_di cpu_regs.di.w -#define reg_edi cpu_regs.di.d -#define reg_sp cpu_regs.sp.w -#define reg_esp cpu_regs.sp.d +enum REG_NUM { + REG_NUM_AX, REG_NUM_CX, REG_NUM_DX, REG_NUM_BX, + REG_NUM_SP, REG_NUM_BP, REG_NUM_SI, REG_NUM_DI +}; -#define reg_bp cpu_regs.bp.w -#define reg_ebp cpu_regs.bp.d +//macros to convert a 3-bit register index to the correct register +#define reg_8l(reg) (cpu_regs.regs[(reg)].b.l) +#define reg_8h(reg) (cpu_regs.regs[(reg)].b.h) +#define reg_8(reg) ((reg) & 4 ? reg_8h((reg) & 3) : reg_8l((reg) & 3)) +#define reg_16(reg) (cpu_regs.regs[(reg)].w) +#define reg_32(reg) (cpu_regs.regs[(reg)].d) + +#define reg_al cpu_regs.regs[REG_NUM_AX].b.l +#define reg_ah cpu_regs.regs[REG_NUM_AX].b.h +#define reg_ax cpu_regs.regs[REG_NUM_AX].w +#define reg_eax cpu_regs.regs[REG_NUM_AX].d + +#define reg_bl cpu_regs.regs[REG_NUM_BX].b.l +#define reg_bh cpu_regs.regs[REG_NUM_BX].b.h +#define reg_bx cpu_regs.regs[REG_NUM_BX].w +#define reg_ebx cpu_regs.regs[REG_NUM_BX].d + +#define reg_cl cpu_regs.regs[REG_NUM_CX].b.l +#define reg_ch cpu_regs.regs[REG_NUM_CX].b.h +#define reg_cx cpu_regs.regs[REG_NUM_CX].w +#define reg_ecx cpu_regs.regs[REG_NUM_CX].d + +#define reg_dl cpu_regs.regs[REG_NUM_DX].b.l +#define reg_dh cpu_regs.regs[REG_NUM_DX].b.h +#define reg_dx cpu_regs.regs[REG_NUM_DX].w +#define reg_edx cpu_regs.regs[REG_NUM_DX].d + +#define reg_si cpu_regs.regs[REG_NUM_SI].w +#define reg_esi cpu_regs.regs[REG_NUM_SI].d + +#define reg_di cpu_regs.regs[REG_NUM_DI].w +#define reg_edi cpu_regs.regs[REG_NUM_DI].d + +#define reg_sp cpu_regs.regs[REG_NUM_SP].w +#define reg_esp cpu_regs.regs[REG_NUM_SP].d + +#define reg_bp cpu_regs.regs[REG_NUM_BP].w +#define reg_ebp cpu_regs.regs[REG_NUM_BP].d #define reg_ip cpu_regs.ip.w #define reg_eip cpu_regs.ip.d - - - - #endif diff --git a/settings.h b/settings.h index f7fefd0..b3933b3 100644 --- a/settings.h +++ b/settings.h @@ -1,21 +1,56 @@ -/* Enable the debugger */ -//#define C_DEBUG +/* + * 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. + */ -/* Enable logging of debug information */ -//#define C_LOGGING +#ifndef _SETTINGS_H_ +#define _SETTINSG_H_ + +/* Enable the debugger, this only seems to work in win32 for now. */ +#define C_DEBUG 0 + +/* Enable the logging of extra information for debugging to the console */ +#define C_LOGGING 0 /* Use multi threading to speed up things on multi cpu's, also gives a nice frame-skipping effect :) */ -#define C_THREADED +#define C_THREADED 1 -/* Enable debugging for several modules, requires C_LOGGING */ -#define DEBUG_SBLASTER /* SoundBlaster Debugging*/ -#define DEBUG_DMA /* DMA Debugging */ -#define DEBUG_DOS /* DOS Debugging */ +/* Enable some big compile-time increasing inlines, great for speed though */ +#define C_EXTRAINLINE 0 +/* Enable the FPU module, still only for beta testing */ +#define C_FPU 0 + +/* Maximum memory range in megabytes */ +#define C_MEM_MAX_SIZE 12 + +/* Maximum memory available for xms, should be lower than maxsize-1 */ +#define C_MEM_XMS_SIZE 8 + +/* Maximum memory available for ems, should be lower than 32 */ +#define C_MEM_EMS_SIZE 4 + +/* Enable debug messages for several modules, requires C_LOGGING */ +#define DEBUG_SBLASTER 0 /* SoundBlaster Debugging*/ +#define DEBUG_DMA 0 /* DMA Debugging */ +#define DEBUG_DOS 0 /* DOS Debugging */ #define LOG_MSG S_Warn -#ifdef C_LOGGING +#if C_LOGGING #define LOG_DEBUG S_Warn #define LOG_WARN S_Warn #define LOG_ERROR S_Warn @@ -23,4 +58,6 @@ #define LOG_DEBUG #define LOG_WARN #define LOG_ERROR -#endif \ No newline at end of file +#endif + +#endif diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index 5794bd4..d10d5e7 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -32,14 +32,13 @@ CallBack_Handler CallBack_Handlers[CB_MAX]; -static Bitu call_runint16,call_idle,call_default,call_runfar16; +static Bitu call_stop,call_idle,call_default; static Bitu illegal_handler(void) { E_Exit("Illegal CallBack Called"); return 1; } -/* when this returns -1 all CallBacks are taken */ Bitu CALLBACK_Allocate(void) { for (Bitu i=0;(i= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;} \ + else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);} \ + } + #define INTERRUPT(blah) \ { \ Bit8u new_num=blah; \ @@ -257,207 +264,248 @@ //TODO Maybe make this into a bigger split up because of the rm >=0xc0 this seems make it a bit slower //TODO set Zero and Sign flag in one run #define ROLB(op1,op2,load,save) \ - if (!(op2&0x07)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var1.b=load(op1);flags.var2.b=op2&0x07; \ - flags.result.b=(flags.var1.b << flags.var2.b) | \ + flags.var2.b=op2&0x07;flags.var1.b=load(op1); \ + if (!flags.var2.b) { \ + flags.result.b=flags.var1.b; \ + } else { \ + flags.result.b=(flags.var1.b << flags.var2.b) | \ (flags.var1.b >> (8-flags.var2.b)); \ + } \ save(op1,flags.result.b); \ flags.type=t_ROLb; #define ROLW(op1,op2,load,save) \ - if (!(op2&0x0F)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \ - flags.result.w=(flags.var1.w << flags.var2.b) | \ - (flags.var1.w >> (16-flags.var2.b)); \ + flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \ + if (!flags.var2.b) { \ + flags.result.w=flags.var1.w; \ + } else { \ + flags.result.w=(flags.var1.w << flags.var2.b) | \ + (flags.var1.w >> (16-flags.var2.b)); \ + } \ save(op1,flags.result.w); \ flags.type=t_ROLw; - #define ROLD(op1,op2,load,save) \ - if (!(op2&0x0F)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \ + flags.var2.b=op2;flags.var1.d=load(op1); \ flags.result.d=(flags.var1.d << flags.var2.b) | \ - (flags.var1.d >> (32-flags.var2.b)); \ + (flags.var1.d >> (32-flags.var2.b)); \ save(op1,flags.result.d); \ flags.type=t_ROLd; #define RORB(op1,op2,load,save) \ - if (!(op2&0x07)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var1.b=load(op1);flags.var2.b=op2&0x07; \ - flags.result.b=(flags.var1.b >> flags.var2.b) | \ + flags.var2.b=op2&0x07;flags.var1.b=load(op1); \ + if (!flags.var2.b) { \ + flags.result.b=flags.var1.b; \ + } else { \ + flags.result.b=(flags.var1.b >> flags.var2.b) | \ (flags.var1.b << (8-flags.var2.b)); \ + } \ save(op1,flags.result.b); \ flags.type=t_RORb; - #define RORW(op1,op2,load,save) \ - if (!(op2&0x0F)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \ - flags.result.w=(flags.var1.w >> flags.var2.b) | \ - (flags.var1.w << (16-flags.var2.b)); \ + flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \ + if (!flags.var2.b) { \ + flags.result.w=flags.var1.w; \ + } else { \ + flags.result.w=(flags.var1.w >> flags.var2.b) | \ + (flags.var1.w << (16-flags.var2.b)); \ + } \ save(op1,flags.result.w); \ flags.type=t_RORw; #define RORD(op1,op2,load,save) \ - if (!(op2&0x0F)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \ + flags.var2.b=op2;flags.var1.d=load(op1); \ flags.result.d=(flags.var1.d >> flags.var2.b) | \ - (flags.var1.d << (32-flags.var2.b)); \ + (flags.var1.d << (32-flags.var2.b)); \ save(op1,flags.result.d); \ flags.type=t_RORd; + +/* flags.oldcf=get_CF();*/ \ + #define RCLB(op1,op2,load,save) \ - if (!(op2%9)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ flags.cf=get_CF();flags.type=t_RCLb; \ - flags.var1.b=load(op1);flags.var2.b=op2%9; \ - flags.result.b=(flags.var1.b << flags.var2.b) | \ - (flags.cf << (flags.var2.b-1)) | \ + flags.var2.b=op2%9;flags.var1.b=load(op1); \ + if (!flags.var2.b) { \ + flags.result.b=flags.var1.b; \ + } else { \ + flags.result.b=(flags.var1.b << flags.var2.b) | \ + (flags.cf << (flags.var2.b-1)) | \ (flags.var1.b >> (9-flags.var2.b)); \ - save(op1,flags.result.b); + flags.cf=((flags.var1.b >> (8-flags.var2.b)) & 1); \ + } \ + flags.of=((flags.result.b & 0x80) ^ (flags.cf ? 0x80 : 0)) != 0; \ + save(op1,flags.result.b); #define RCLW(op1,op2,load,save) \ - if (!(op2%17)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ flags.cf=get_CF();flags.type=t_RCLw; \ - flags.var1.w=load(op1);flags.var2.b=op2%17; \ - flags.result.w=(flags.var1.w << flags.var2.b) | \ - (flags.cf << (flags.var2.b-1)) | \ - (flags.var1.w >> (17-flags.var2.b)); \ + flags.var2.b=op2%17;flags.var1.w=load(op1); \ + if (!flags.var2.b) { \ + flags.result.w=flags.var1.w; \ + } else { \ + flags.result.w=(flags.var1.w << flags.var2.b) | \ + (flags.cf << (flags.var2.b-1)) | \ + (flags.var1.w >> (17-flags.var2.b)); \ + flags.cf=((flags.var1.w >> (16-flags.var2.b)) & 1); \ + } \ + flags.of=((flags.result.w & 0x8000) ^ (flags.cf ? 0x8000 : 0)) != 0; \ save(op1,flags.result.w); #define RCLD(op1,op2,load,save) \ - if (!op2) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ flags.cf=get_CF();flags.type=t_RCLd; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ - if (flags.var2.b==1) { \ - flags.result.d=flags.var1.d << 1 | flags.cf; \ + flags.var2.b=op2;flags.var1.d=load(op1); \ + if (flags.var2.b==1) { \ + flags.result.d=flags.var1.d << 1 | flags.cf; \ } else { \ flags.result.d=(flags.var1.d << flags.var2.b) | \ - (flags.cf << (flags.var2.b-1)) | \ - (flags.var1.d >> (33-flags.var2.b)); \ + (flags.cf << (flags.var2.b-1)) | \ + (flags.var1.d >> (33-flags.var2.b)); \ } \ + flags.cf=((flags.var1.d >> (32-flags.var2.b)) & 1); \ + flags.of=((flags.result.d & 0x80000000) ^ (flags.cf ? 0x80000000 : 0)) != 0; \ save(op1,flags.result.d); #define RCRB(op1,op2,load,save) \ - if (!(op2%9)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ flags.cf=get_CF();flags.type=t_RCRb; \ - flags.var1.b=load(op1);flags.var2.b=op2%9; \ - flags.result.b=(flags.var1.b >> flags.var2.b) | \ - (flags.cf << (8-flags.var2.b)) | \ + flags.var2.b=op2%9;flags.var1.b=load(op1); \ + if (!flags.var2.b) { \ + flags.result.b=flags.var1.b; \ + } else { \ + flags.result.b=(flags.var1.b >> flags.var2.b) | \ + (flags.cf << (8-flags.var2.b)) | \ (flags.var1.b << (9-flags.var2.b)); \ + } \ save(op1,flags.result.b); #define RCRW(op1,op2,load,save) \ - if (!(op2%17)) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ flags.cf=get_CF();flags.type=t_RCRw; \ - flags.var1.w=load(op1);flags.var2.b=op2%17; \ - flags.result.w=(flags.var1.w >> flags.var2.b) | \ + flags.var2.b=op2%17;flags.var1.w=load(op1); \ + if (!flags.var2.b) { \ + flags.result.w=flags.var1.w; \ + } else { \ + flags.result.w=(flags.var1.w >> flags.var2.b) | \ (flags.cf << (16-flags.var2.b)) | \ - (flags.var1.w << (17-flags.var2.b)); \ + (flags.var1.w << (17-flags.var2.b)); \ + } \ save(op1,flags.result.w); - #define RCRD(op1,op2,load,save) \ - if (!op2) break; \ + if (!op2) break; \ flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ flags.cf=get_CF();flags.type=t_RCRd; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ + flags.var2.b=op2;flags.var1.d=load(op1); \ if (flags.var2.b==1) { \ flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \ } else { \ flags.result.d=(flags.var1.d >> flags.var2.b) | \ (flags.cf << (32-flags.var2.b)) | \ - (flags.var1.d << (33-flags.var2.b)); \ + (flags.var1.d << (33-flags.var2.b)); \ } \ save(op1,flags.result.d); + #define SHLB(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b << flags.var2.b; \ + if (!op2) break; \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b << flags.var2.b; \ save(op1,flags.result.b); \ flags.type=t_SHLb; #define SHLW(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2; \ - flags.result.w=flags.var1.w << flags.var2.b; \ + if (!op2) break; \ + flags.var1.w=load(op1);flags.var2.b=op2 ; \ + flags.result.w=flags.var1.w << flags.var2.b; \ save(op1,flags.result.w); \ flags.type=t_SHLw; #define SHLD(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ - flags.result.d=flags.var1.d << flags.var2.b; \ + if (!op2) break; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + flags.result.d=flags.var1.d << flags.var2.b; \ save(op1,flags.result.d); \ flags.type=t_SHLd; + #define SHRB(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b >> flags.var2.b; \ + if (!op2) break; \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b >> flags.var2.b; \ save(op1,flags.result.b); \ flags.type=t_SHRb; #define SHRW(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2; \ - flags.result.w=flags.var1.w >> flags.var2.b; \ + if (!op2) break; \ + flags.var1.w=load(op1);flags.var2.b=op2; \ + flags.result.w=flags.var1.w >> flags.var2.b; \ save(op1,flags.result.w); \ flags.type=t_SHRw; #define SHRD(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ - flags.result.d=flags.var1.d >> flags.var2.b; \ + if (!op2) break; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + flags.result.d=flags.var1.d >> flags.var2.b; \ save(op1,flags.result.d); \ flags.type=t_SHRd; + #define SARB(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ + if (!op2) break; \ + flags.var1.b=load(op1);flags.var2.b=op2; \ if (flags.var2.b>8) flags.var2.b=8; \ if (flags.var1.b & 0x80) { \ - flags.result.b=(flags.var1.b >> flags.var2.b)| \ + flags.result.b=(flags.var1.b >> flags.var2.b)| \ (0xff << (8 - flags.var2.b)); \ } else { \ - flags.result.b=flags.var1.b >> flags.var2.b; \ + flags.result.b=flags.var1.b >> flags.var2.b; \ } \ save(op1,flags.result.b); \ flags.type=t_SARb; #define SARW(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2; \ - if (flags.var2.b>16) flags.var2.b=16; \ - if (flags.var1.w & 0x8000) { \ - flags.result.w=(flags.var1.w >> flags.var2.b)| \ - (0xffff << (16 - flags.var2.b)); \ + if (!op2) break; \ + flags.var1.w=load(op1);flags.var2.b=op2; \ + if (flags.var2.b>16) flags.var2.b=16; \ + if (flags.var1.w & 0x8000) { \ + flags.result.w=(flags.var1.w >> flags.var2.b)| \ + (0xffff << (16 - flags.var2.b)); \ } else { \ - flags.result.w=flags.var1.w >> flags.var2.b; \ + flags.result.w=flags.var1.w >> flags.var2.b; \ } \ save(op1,flags.result.w); \ flags.type=t_SARw; #define SARD(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ - if (flags.var1.d & 0x80000000) { \ - flags.result.d=(flags.var1.d >> flags.var2.b)| \ - (0xffffffff << (32 - flags.var2.b)); \ + if (!op2) break; \ + flags.var2.b=op2;flags.var1.d=load(op1); \ + if (flags.var1.d & 0x80000000) { \ + flags.result.d=(flags.var1.d >> flags.var2.b)| \ + (0xffffffff << (32 - flags.var2.b)); \ } else { \ - flags.result.d=flags.var1.d >> flags.var2.b; \ + flags.result.d=flags.var1.d >> flags.var2.b; \ } \ save(op1,flags.result.d); \ flags.type=t_SARd; @@ -564,30 +612,43 @@ } /* let's hope bochs has it correct with the higher than 16 shifts */ +/* double-precision shift left has low bits in second argument */ #define DSHLW(op1,op2,op3,load,save) \ - flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \ + Bit8u val=op3 & 0x1F; \ + if (!val) break; \ + flags.var2.b=val;flags.var1.d=(load(op1)<<16)|op2; \ Bit32u tempd=flags.var1.d << flags.var2.b; \ if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \ flags.result.w=(Bit16u)(tempd >> 16); \ save(op1,flags.result.w); \ flags.type=t_DSHLw; -#define DSHLD(op1,op2,op3,load,save) \ - flags.var1.d=load(op1);flags.var2.b=op3; \ +#define DSHLD(op1,op2,op3,load,save) \ + Bit8u val=op3 & 0x1F; \ + if (!val) break; \ + flags.var2.b=val;flags.var1.d=load(op1); \ flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \ - save(op1,flags.result.d); \ + save(op1,flags.result.d); \ flags.type=t_DSHLd; +/* double-precision shift right has high bits in second argument */ #define DSHRW(op1,op2,op3,load,save) \ - flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \ + Bit8u val=op3 & 0x1F; \ + if (!val) break; \ + flags.var2.b=val;flags.var1.d=(op2<<16)|load(op1); \ Bit32u tempd=flags.var1.d >> flags.var2.b; \ if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \ flags.result.w=(Bit16u)(tempd); \ save(op1,flags.result.w); \ flags.type=t_DSHRw; -#define DSHRD(op1,op2,op3,load,save) \ - flags.var1.d=load(op1);flags.var2.b=op3; \ +#define DSHRD(op1,op2,op3,load,save) \ + Bit8u val=op3 & 0x1F; \ + if (!val) break; \ + flags.var2.b=val;flags.var1.d=load(op1); \ flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \ - save(op1,flags.result.d); \ + save(op1,flags.result.d); \ flags.type=t_DSHRd; + +#define BSWAP(op1) \ + op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000); diff --git a/src/cpu/core_16/main.h b/src/cpu/core_16/main.h index 2e9dd4b..9d72cf2 100644 --- a/src/cpu/core_16/main.h +++ b/src/cpu/core_16/main.h @@ -32,9 +32,9 @@ restart: case 0x05: /* ADD AX,Iw */ AXIw(ADDW);break; case 0x06: /* PUSH ES */ - Push_16(Segs[es].value);break; + Push_16(SegValue(es));break; case 0x07: /* POP ES */ - SetSegment_16(es,Pop_16());break; + SegSet16(es,Pop_16());break; case 0x08: /* OR Eb,Gb */ RMEbGb(ORB);break; case 0x09: /* OR Ew,Gw */ @@ -48,7 +48,7 @@ restart: case 0x0d: /* OR AX,Iw */ AXIw(ORW);break; case 0x0e: /* PUSH CS */ - Push_16(Segs[cs].value);break; + Push_16(SegValue(cs));break; case 0x0f: /* 2 byte opcodes*/ #include "prefix_of.h" break; @@ -65,9 +65,9 @@ restart: case 0x15: /* ADC AX,Iw */ AXIw(ADCW);break; case 0x16: /* PUSH SS */ - Push_16(Segs[ss].value);break; + Push_16(SegValue(ss));break; case 0x17: /* POP SS */ - SetSegment_16(ss,Pop_16());break; + SegSet16(ss,Pop_16());break; case 0x18: /* SBB Eb,Gb */ RMEbGb(SBBB);break; case 0x19: /* SBB Ew,Gw */ @@ -81,9 +81,9 @@ restart: case 0x1d: /* SBB AX,Iw */ AXIw(SBBW);break; case 0x1e: /* PUSH DS */ - Push_16(Segs[ds].value);break; + Push_16(SegValue(ds));break; case 0x1f: /* POP DS */ - SetSegment_16(ds,Pop_16());break; + SegSet16(ds,Pop_16());break; case 0x20: /* AND Eb,Gb */ RMEbGb(ANDB);break; case 0x21: /* AND Ew,Gw */ @@ -235,9 +235,9 @@ restart: Push_16(reg_dx);break; case 0x53: /* PUSH BX */ Push_16(reg_bx);break; - case 0x54: /* PUSH SP */ + case 0x54: /* PUSH SP */ //TODO Check if this is correct i think it's SP+2 or something - Push_16(reg_sp);break; + Push_16(reg_sp);break; case 0x55: /* PUSH BP */ Push_16(reg_bp);break; case 0x56: /* PUSH SI */ @@ -252,8 +252,8 @@ restart: reg_dx=Pop_16();break; case 0x5b: /* POP BX */ reg_bx=Pop_16();break; - case 0x5c: /* POP SP */ - reg_sp=Pop_16();break; + case 0x5c: /* POP SP */ + reg_sp=Pop_16();break; case 0x5d: /* POP BP */ reg_bp=Pop_16();break; case 0x5e: /* POP SI */ @@ -274,7 +274,7 @@ restart: GetRMrw;GetEAa; bound_min=LoadMw(eaa); bound_max=LoadMw(eaa+2); - if ( (*rmrw < bound_min) || (*rmrw > bound_max) ) { + if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) { INTERRUPT(5); } } @@ -524,17 +524,17 @@ restart: GetRM;Bit16u val; switch (rm & 0x38) { case 0x00: /* MOV Ew,ES */ - val=Segs[es].value;break; + val=SegValue(es);break; case 0x08: /* MOV Ew,CS */ - val=Segs[cs].value;break; + val=SegValue(cs);break; case 0x10: /* MOV Ew,SS */ - val=Segs[ss].value;break; + val=SegValue(ss);break; case 0x18: /* MOV Ew,DS */ - val=Segs[ds].value;break; + val=SegValue(ds);break; case 0x20: /* MOV Ew,FS */ - val=Segs[fs].value;break; + val=SegValue(fs);break; case 0x28: /* MOV Ew,GS */ - val=Segs[gs].value;break; + val=SegValue(gs);break; default: val=0; E_Exit("CPU:8c:Illegal RM Byte"); @@ -583,18 +583,18 @@ restart: else {GetEAa;val=LoadMw(eaa);} switch (rm & 0x38) { case 0x00: /* MOV ES,Ew */ - SetSegment_16(es,val);break; + SegSet16(es,val);break; case 0x08: /* MOV CS,Ew Illegal*/ E_Exit("CPU:Illegal MOV CS Call"); break; case 0x10: /* MOV SS,Ew */ - SetSegment_16(ss,val);break; + SegSet16(ss,val);break; case 0x18: /* MOV DS,Ew */ - SetSegment_16(ds,val);break; + SegSet16(ds,val);break; case 0x20: /* MOV FS,Ew */ - SetSegment_16(fs,val);break; + SegSet16(fs,val);break; case 0x28: /* MOV GS,Ew */ - SetSegment_16(gs,val);break; + SegSet16(gs,val);break; default: E_Exit("CPU:8e:Illegal RM Byte"); } @@ -639,8 +639,8 @@ restart: case 0x9a: /* CALL Ap */ { Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); - Push_16(Segs[cs].value);Push_16(GETIP); - SetSegment_16(cs,newcs);SETIP(newip); + Push_16(SegValue(cs));Push_16(GETIP); + SegSet16(cs,newcs);SETIP(newip); break; } case 0x9b: /* WAIT */ @@ -675,35 +675,27 @@ restart: break; } case 0xa0: /* MOV AL,Ob */ - if (segprefix_on) { - reg_al=LoadMb(segprefix_base+Fetchw()); - SegPrefixReset; - } else { - reg_al=LoadMb(SegBase(ds)+Fetchw()); + { + GetEADirect; + reg_al=LoadMb(eaa); } break; case 0xa1: /* MOV AX,Ow */ - if (segprefix_on) { - reg_ax=LoadMw(segprefix_base+Fetchw()); - SegPrefixReset; - } else { - reg_ax=LoadMw(SegBase(ds)+Fetchw()); + { + GetEADirect; + reg_ax=LoadMw(eaa); } break; case 0xa2: /* MOV Ob,AL */ - if (segprefix_on) { - SaveMb((segprefix_base+Fetchw()),reg_al); - SegPrefixReset; - } else { - SaveMb((SegBase(ds)+Fetchw()),reg_al); + { + GetEADirect; + SaveMb(eaa,reg_al); } break; case 0xa3: /* MOV Ow,AX */ - if (segprefix_on) { - SaveMw((segprefix_base+Fetchw()),reg_ax); - SegPrefixReset; - } else { - SaveMw((SegBase(ds)+Fetchw()),reg_ax); + { + GetEADirect; + SaveMw(eaa,reg_ax); } break; case 0xa4: /* MOVSB */ @@ -838,13 +830,13 @@ restart: case 0xc4: /* LES */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SetSegment_16(es,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa);SegSet16(es,LoadMw(eaa+2)); break; } case 0xc5: /* LDS */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SetSegment_16(ds,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa);SegSet16(ds,LoadMw(eaa+2)); break; } case 0xc6: /* MOV Eb,Ib */ @@ -876,21 +868,28 @@ restart: { Bit16u addsp=Fetchw(); Bit16u newip=Pop_16();Bit16u newcs=Pop_16(); - reg_sp+=addsp;SetSegment_16(cs,newcs);SETIP(newip); + reg_sp+=addsp;SegSet16(cs,newcs);SETIP(newip); break; } case 0xcb: /* RETF */ { Bit16u newip=Pop_16();Bit16u newcs=Pop_16(); - SetSegment_16(cs,newcs);SETIP(newip); + SegSet16(cs,newcs);SETIP(newip); } break; case 0xcc: /* INT3 */ INTERRUPT(3); +#if C_DEBUG + return 0; +#endif break; case 0xcd: /* INT Ib */ { Bit8u num=Fetchb(); +#if C_DEBUG + SAVEIP; + if (DEBUG_IntBreakpoint(num)) return 0; +#endif INTERRUPT(num); } break; @@ -900,7 +899,7 @@ restart: case 0xcf: /* IRET */ { Bit16u newip=Pop_16();Bit16u newcs=Pop_16(); - SetSegment_16(cs,newcs);SETIP(newip); + SegSet16(cs,newcs);SETIP(newip); Bit16u pflags=Pop_16();Save_Flagsw(pflags); break; } @@ -933,17 +932,35 @@ restart: //TODO PF flags.type=t_UNKNOWN; break; - case 0xd6: /* Not in intel specs */ - NOTDONE; + case 0xd6: /* SALC */ + reg_al = get_CF() ? 0xFF : 0; break; case 0xd7: /* XLAT */ - if (segprefix_on) { + if (prefixes & PREFIX_SEG) { reg_al=LoadMb(segprefix_base+(Bit16u)(reg_bx+reg_al)); - SegPrefixReset; + PrefixReset; } else { reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al)); } break; +#ifdef CPU_FPU + case 0xd8: /* FPU ESC 0 */ + FPU_ESC(0);break; + case 0xd9: /* FPU ESC 1 */ + FPU_ESC(1);break; + case 0xda: /* FPU ESC 2 */ + FPU_ESC(2);break; + case 0xdb: /* FPU ESC 3 */ + FPU_ESC(3);break; + case 0xdc: /* FPU ESC 4 */ + FPU_ESC(4);break; + case 0xdd: /* FPU ESC 5 */ + FPU_ESC(5);break; + case 0xde: /* FPU ESC 6 */ + FPU_ESC(6);break; + case 0xdf: /* FPU ESC 7 */ + FPU_ESC(7);break; +#else case 0xd8: /* FPU ESC 0 */ case 0xd9: /* FPU ESC 1 */ case 0xda: /* FPU ESC 2 */ @@ -954,15 +971,10 @@ restart: case 0xdf: /* FPU ESC 7 */ { Bit8u rm=Fetchb(); - if (rm>=0xc0) { - FPU_ESC0_Normal(rm); - } else { - GetEAa;FPU_ESC0_EA(rm,eaa); - } - break; + if (rm<0xc0) GetEAa; } - break; +#endif case 0xe0: /* LOOPNZ */ if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs()); else ADDIPFAST(1); @@ -1005,7 +1017,7 @@ restart: { Bit16u newip=Fetchw(); Bit16u newcs=Fetchw(); - SetSegment_16(cs,newcs); + SegSet16(cs,newcs); SETIP(newip); break; } @@ -1041,9 +1053,9 @@ restart: { EAPoint to=SegBase(es); EAPoint from; - if (segprefix_on) { + if (prefixes & PREFIX_SEG) { from=(segprefix_base); - SegPrefixReset; + PrefixReset; } else { from=SegBase(ds); } @@ -1453,11 +1465,11 @@ restart: break; case 0x18: /* CALL Ep */ { - Push_16(Segs[cs].value); + Push_16(SegValue(cs)); GetEAa;Push_16(GETIP); Bit16u newip=LoadMw(eaa); Bit16u newcs=LoadMw(eaa+2); - SetSegment_16(cs,newcs); + SegSet16(cs,newcs); SETIP(newip); } break; @@ -1470,7 +1482,7 @@ restart: GetEAa; Bit16u newip=LoadMw(eaa); Bit16u newcs=LoadMw(eaa+2); - SetSegment_16(cs,newcs); + SegSet16(cs,newcs); SETIP(newip); } break; diff --git a/src/cpu/core_16/prefix_66.h b/src/cpu/core_16/prefix_66.h index 5af2a12..d34ad4b 100644 --- a/src/cpu/core_16/prefix_66.h +++ b/src/cpu/core_16/prefix_66.h @@ -230,6 +230,8 @@ switch(Fetchb()) { } } break; + case 0x85: /* TEST Ed,Gd */ + RMEdGd(TESTD);break; case 0x8f: /* POP Ed */ { GetRM; @@ -271,23 +273,20 @@ switch(Fetchb()) { } case 0x9d: /* POPFD */ { - Save_Flagsw((Bit16u)(Pop_32()&0xffff)); + Bit16u val=(Bit16u)(Pop_32()&0xffff); + Save_Flagsw(val); break; } case 0xa1: /* MOV EAX,Ow */ - if (segprefix_on) { - reg_eax=LoadMd(segprefix_base+Fetchw()); - SegPrefixReset; - } else { - reg_eax=LoadMd(SegBase(ds)+Fetchw()); + { + GetEADirect; + reg_eax=LoadMd(eaa); } break; case 0xa3: /* MOV Ow,EAX */ - if (segprefix_on) { - SaveMd((segprefix_base+Fetchw()),reg_eax); - SegPrefixReset; - } else { - SaveMd((SegBase(ds)+Fetchw()),reg_eax); + { + GetEADirect; + SaveMd(eaa,reg_eax); } break; case 0xa5: /* MOVSD */ @@ -411,13 +410,13 @@ switch(Fetchb()) { Bit32u val; if (rm >= 0xc0 ) {GetEArd;val=*eard;} else {GetEAa;val=LoadMd(eaa);} - if (val==0) {Interrupt(0);break;} + if (val==0) {INTERRUPT(0);break;} temp.u=(((Bit64u)reg_edx)<<32)|reg_eax; quotient.u=temp.u/val; reg_edx=(Bit32u)(temp.u % val); reg_eax=(Bit32u)(quotient.u & 0xffffffff); if (quotient.u>0xffffffff) - Interrupt(0); + INTERRUPT(0); break; } case 0x38: /* IDIV Ed */ @@ -426,13 +425,13 @@ switch(Fetchb()) { Bit32s val; if (rm >= 0xc0 ) {GetEArd;val=*eards;} else {GetEAa;val=LoadMds(eaa);} - if (val==0) {Interrupt(0);break;} + if (val==0) {INTERRUPT(0);break;} temp.s=(((Bit64u)reg_edx)<<32)|reg_eax; quotient.s=(temp.s/val); reg_edx=(Bit32s)(temp.s % val); reg_eax=(Bit32s)(quotient.s); if (quotient.s!=(Bit32s)reg_eax) - Interrupt(0); + INTERRUPT(0); break; } } diff --git a/src/cpu/core_16/prefix_of.h b/src/cpu/core_16/prefix_of.h index f402499..3decea1 100644 --- a/src/cpu/core_16/prefix_of.h +++ b/src/cpu/core_16/prefix_of.h @@ -17,6 +17,19 @@ */ switch(Fetchb()) { + case 0x00: /* GRP 6 */ + { + INTERRUPT(6); + break; + GetRM; + switch (rm & 0x38) { + case 0x00: + default: + E_Exit("CPU:GRP6:Illegal call %2X",(rm>>3) &3); + } + } + break; + case 0x01: /* GRP 7 */ { GetRM; @@ -27,10 +40,67 @@ switch(Fetchb()) { else {GetEAa;SaveMw(eaa,0);} break; default: - E_Exit("CPU:GRP7:Illegal call %2X",rm); + E_Exit("CPU:GRP7:Illegal call %2X",(rm>>3) &3); } } break; + /* 0x02 LAR Gw,Ew (286) */ + /* 0x03 LSL Gw,Ew (286) */ + /* 0x05 LOADALL (286 only?) */ + /* 0x06 CLTS (286) */ + /* 0x07 LOADALL (386 only?) */ + /* 0x08 INVD (486) */ + /* 0x02 WBINVD (486) */ + /* 0x10 UMOV Eb,Gb (386) */ + /* 0x11 UMOV Ew,Gw (386) */ + /* 0x12 UMOV Gb,Eb (386) */ + /* 0x13 UMOV Gw,Ew (386) */ + /* 0x20 MOV Rd,CRx (386) */ + /* 0x21 MOV Rd,DRx (386) */ + /* 0x22 MOV CRx,Rd (386) */ + /* 0x23 MOV DRx,Rd (386) */ + /* 0x24 MOV Rd,TRx (386) */ + /* 0x26 MOV TRx,Rd (386) */ + /* 0x30 WRMSR (P5) */ + /* 0x31 RDTSC (P5) */ + /* 0x32 RDMSR (P5) */ + /* 0x33 RDPMC (P6) */ + /* 0x40-4F CMOVcc Gw,Ew (P6) */ + /* 0x50 PAVEB Rq,Eq (CYRIX MMX) */ + /* 0x51 PADDSIW Rq,Eq (CYRIX MMX) */ + /* 0x52 PMAGW Rq,Eq (CYRIX MMX) */ + /* 0x54 PDISTIB Rq,Eq (CYRIX MMX) */ + /* 0x55 PSUBSIW Rq,Eq (CYRIX MMX) */ + /* 0x58 PMVZB Rq,Eq (CYRIX MMX) */ + /* 0x59 PMULHRW Rq,Eq (CYRIX MMX) */ + /* 0x5A PMVNZB Rq,Eq (CYRIX MMX) */ + /* 0x5B PMVLZB Rq,Eq (CYRIX MMX) */ + /* 0x5C PMVGEZB Rq,Eq (CYRIX MMX) */ + /* 0x5D PMULHRIW Rq,Eq (CYRIX MMX) */ + /* 0x5E PMACHRIW Rq,Eq (CYRIX MMX) */ + /* 0x60 PUNPCKLBW Rq,Eq (MMX) */ + /* 0x61 PUNPCKLWD Rq,Eq (MMX) */ + /* 0x62 PUNPCKLDQ Rq,Eq (MMX) */ + /* 0x63 PACKSSWB Rq,Eq (MMX) */ + /* 0x64 PCMPGTB Rq,Eq (MMX) */ + /* 0x65 PCMPGTW Rq,Eq (MMX) */ + /* 0x66 PCMPGTD Rq,Eq (MMX) */ + /* 0x67 PACKUSWB Rq,Eq (MMX) */ + /* 0x68 PUNPCKHBW Rq,Eq (MMX) */ + /* 0x69 PUNPCKHWD Rq,Eq (MMX) */ + /* 0x6A PUNPCKHDQ Rq,Eq (MMX) */ + /* 0x6B PACKSSDW Rq,Eq (MMX) */ + /* 0x6E MOVD Rq,Ed (MMX) */ + /* 0x6F MOVQ Rq,Eq (MMX) */ + /* 0x71 PSLLW/PSRAW/PSRLW Rq,Ib (MMX) */ + /* 0x72 PSLLD/PSRAD/PSRLD Rq,Ib (MMX) */ + /* 0x73 PSLLQ/PSRLQ Rq,Ib (MMX) */ + /* 0x74 PCMPEQB Rq,Eq (MMX) */ + /* 0x75 PCMPEQW Rq,Eq (MMX) */ + /* 0x76 PCMPEQD Rq,Eq (MMX) */ + /* 0x77 EMMS (MMX) */ + /* 0x7E MOVD Ed,Rq (MMX) */ + /* 0x7F MOVQ Ed,Rq (MMX) */ case 0x80: /* JO */ JumpSIw(get_OF());break; case 0x81: /* JNO */ @@ -63,10 +133,59 @@ switch(Fetchb()) { JumpSIw(get_ZF() || (get_SF() != get_OF()));break; case 0x8f: /* JNLE */ JumpSIw((get_SF() == get_OF()) && !get_ZF());break; + + case 0x90: /* SETO */ + SETcc(get_OF());break; + case 0x91: /* SETNO */ + SETcc(!get_OF());break; + case 0x92: /* SETB */ + SETcc(get_CF());break; + case 0x93: /* SETNB */ + SETcc(!get_CF());break; + case 0x94: /* SETZ */ + SETcc(get_ZF());break; + case 0x95: /* SETNZ */ + SETcc(!get_ZF()); break; + case 0x96: /* SETBE */ + SETcc(get_CF() || get_ZF());break; + case 0x97: /* SETNBE */ + SETcc(!get_CF() && !get_ZF());break; + case 0x98: /* SETS */ + SETcc(get_SF());break; + case 0x99: /* SETNS */ + SETcc(!get_SF());break; + case 0x9a: /* SETP */ + SETcc(get_PF());break; + case 0x9b: /* SETNP */ + SETcc(!get_PF());break; + case 0x9c: /* SETL */ + SETcc(get_SF() != get_OF());break; + case 0x9d: /* SETNL */ + SETcc(get_SF() == get_OF());break; + case 0x9e: /* SETLE */ + SETcc(get_ZF() || (get_SF() != get_OF()));break; + case 0x9f: /* SETNLE */ + SETcc((get_SF() == get_OF()) && !get_ZF());break; + case 0xa0: /* PUSH FS */ - Push_16(Segs[fs].value);break; + Push_16(SegValue(fs));break; case 0xa1: /* POP FS */ - SetSegment_16(fs,Pop_16());break; + SegSet16(fs,Pop_16());break; + /* 0xa2 CPUID */ + case 0xa3: /* BT Ew,Gw */ + { + GetRMrw; + Bit16u mask=1 << (*rmrw & 15); + if (rm >= 0xc0 ) { + GetEArw; + flags.cf=(*earw & mask)>0; + } else { + GetEAa;Bit16u old=LoadMw(eaa); + flags.cf=(old & mask)>0; + } + if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } + break; + } case 0xa4: /* SHLD Ew,Gw,Ib */ { GetRMrw; @@ -81,10 +200,29 @@ switch(Fetchb()) { else {GetEAa;DSHLW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);} break; } + /* 0xa6 XBTS (early 386 only) CMPXCHG (early 486 only) */ + /* 0xa7 IBTS (early 386 only) CMPXCHG (early 486 only) */ case 0xa8: /* PUSH GS */ - Push_16(Segs[gs].value);break; + Push_16(SegValue(gs));break; case 0xa9: /* POP GS */ - SetSegment_16(gs,Pop_16());break; + SegSet16(gs,Pop_16());break; + /* 0xaa RSM */ + case 0xab: /* BTS Ew,Gw */ + { + GetRMrw; + Bit16u mask=1 << (*rmrw & 15); + if (rm >= 0xc0 ) { + GetEArw; + flags.cf=(*earw & mask)>0; + *earw|=mask; + } else { + GetEAa;Bit16u old=LoadMw(eaa); + flags.cf=(old & mask)>0; + SaveMw(eaa,old | mask); + } + if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } + break; + } case 0xac: /* SHRD Ew,Gw,Ib */ { GetRMrw; @@ -111,16 +249,35 @@ switch(Fetchb()) { else {flags.cf=true;flags.of=true;} break; } + /* 0xb0 CMPXCHG Eb,Gb */ + /* 0xb1 CMPXCHG Ew,Gw */ + /* 0xb2 LSS */ + case 0xb3: /* BTR Ew,Gw */ + { + GetRMrw; + Bit16u mask=1 << (*rmrw & 15); + if (rm >= 0xc0 ) { + GetEArw; + flags.cf=(*earw & mask)>0; + *earw&= ~mask; + } else { + GetEAa;Bit16u old=LoadMw(eaa); + flags.cf=(old & mask)>0; + SaveMw(eaa,old & ~mask); + } + if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } + break; + } case 0xb4: /* LFS */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SetSegment_16(fs,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa);SegSet16(fs,LoadMw(eaa+2)); break; } case 0xb5: /* LGS */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SetSegment_16(gs,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa);SegSet16(gs,LoadMw(eaa+2)); break; } case 0xb6: /* MOVZX Gw,Eb */ @@ -130,12 +287,20 @@ switch(Fetchb()) { else {GetEAa;*rmrw=LoadMb(eaa);} break; } + case 0xb7: /* MOVZX Gw,Ew */ + case 0xbf: /* MOVSX Gw,Ew */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} + else {GetEAa;*rmrw=LoadMw(eaa);} + break; + } case 0xba: /* GRP8 Ew,Ib */ { GetRM; + Bit16u mask=1 << (Fetchb() & 15); if (rm >= 0xc0 ) { GetEArw; - Bit16u mask=1 << (Fetchb() & 15); flags.cf=(*earw & mask)>0; switch (rm & 0x38) { case 0x20: /* BT */ @@ -144,16 +309,14 @@ switch(Fetchb()) { *earw|=mask; break; case 0x30: /* BTR */ - *earw&=~mask; + *earw&= ~mask; break; case 0x38: /* BTC */ - if (flags.cf) *earw&=~mask; - else *earw|=mask; + *earw^=mask; break; } } else { GetEAa;Bit16u old=LoadMw(eaa); - Bit16u mask=1 << (Fetchb() & 15); flags.cf=(old & mask)>0; switch (rm & 0x38) { case 0x20: /* BT */ @@ -165,16 +328,64 @@ switch(Fetchb()) { SaveMw(eaa,old & ~mask); break; case 0x38: /* BTC */ - if (flags.cf) old&=~mask; - else old|=mask; - SaveMw(eaa,old); + SaveMw(eaa,old ^ mask); break; } } - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; + if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } + case 0xbb: /* BTC Ew,Gw */ + { + GetRMrw; + Bit16u mask=1 << (*rmrw & 15); + if (rm >= 0xc0 ) { + GetEArw; + flags.cf=(*earw & mask)>0; + *earw^=mask; + } else { + GetEAa;Bit16u old=LoadMw(eaa); + flags.cf=(old & mask)>0; + SaveMw(eaa,old ^ mask); + } + if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } + break; + } + case 0xbc: /* 0xbc BSF Gw,Ew */ + { + GetRMrw; + Bit16u result,value; + if (rm >= 0xc0) { GetEArw; value=*earw; } + else { GetEAa; value=LoadMw(eaa); } + if (value==0) { + flags.zf = true; + } else { + result = 0; + while ((value & 0x01)==0) { result++; value>>=1; } + flags.zf = false; + *rmrw = result; + } + flags.type=t_UNKNOWN; + break; + } + case 0xbd: /* 0xbd BSR Gw,Ew */ + { + GetRMrw; + Bit16u result,value; + if (rm >= 0xc0) { GetEArw; value=*earw; } + else { GetEAa; value=LoadMw(eaa); } + if (value==0) { + flags.zf = true; + } else { + result = 15; // Operandsize-1 + while ((value & 0x8000)==0) { result--; value<<=1; } + flags.zf = false; + *rmrw = result; + } + flags.type=t_UNKNOWN; + break; + } + /* 0xbd BSR Gw,Ew */ case 0xbe: /* MOVSX Gw,Eb */ { GetRMrw; @@ -182,6 +393,48 @@ switch(Fetchb()) { else {GetEAa;*rmrw=LoadMbs(eaa);} break; } + /* 0xc0 XADD Eb,Gb (486) */ + /* 0xc1 XADD Ew,Gw (486) */ + /* 0xc7 CMPXCHG8B Mq (P5) */ + /* 0xc8-cf BSWAP Rw (odd behavior,486) */ + case 0xc8: BSWAP(reg_eax); break; + case 0xc9: BSWAP(reg_ecx); break; + case 0xca: BSWAP(reg_edx); break; + case 0xcb: BSWAP(reg_ebx); break; + case 0xcc: BSWAP(reg_esp); break; + case 0xcd: BSWAP(reg_ebp); break; + case 0xce: BSWAP(reg_esi); break; + case 0xcf: BSWAP(reg_edi); break; + + /* 0xd1 PSRLW Rq,Eq (MMX) */ + /* 0xd2 PSRLD Rq,Eq (MMX) */ + /* 0xd3 PSRLQ Rq,Eq (MMX) */ + /* 0xd5 PMULLW Rq,Eq (MMX) */ + /* 0xd8 PSUBUSB Rq,Eq (MMX) */ + /* 0xd9 PSUBUSW Rq,Eq (MMX) */ + /* 0xdb PAND Rq,Eq (MMX) */ + /* 0xdc PADDUSB Rq,Eq (MMX) */ + /* 0xdd PADDUSW Rq,Eq (MMX) */ + /* 0xdf PANDN Rq,Eq (MMX) */ + /* 0xe1 PSRAW Rq,Eq (MMX) */ + /* 0xe2 PSRAD Rq,Eq (MMX) */ + /* 0xe5 PMULHW Rq,Eq (MMX) */ + /* 0xe8 PSUBSB Rq,Eq (MMX) */ + /* 0xe9 PSUBSW Rq,Eq (MMX) */ + /* 0xeb POR Rq,Eq (MMX) */ + /* 0xec PADDSB Rq,Eq (MMX) */ + /* 0xed PADDSW Rq,Eq (MMX) */ + /* 0xef PXOR Rq,Eq (MMX) */ + /* 0xf1 PSLLW Rq,Eq (MMX) */ + /* 0xf2 PSLLD Rq,Eq (MMX) */ + /* 0xf3 PSLLQ Rq,Eq (MMX) */ + /* 0xf5 PMADDWD Rq,Eq (MMX) */ + /* 0xf8 PSUBB Rq,Eq (MMX) */ + /* 0xf9 PSUBW Rq,Eq (MMX) */ + /* 0xfa PSUBD Rq,Eq (MMX) */ + /* 0xfc PADDB Rq,Eq (MMX) */ + /* 0xfd PADDW Rq,Eq (MMX) */ + /* 0xfe PADDD Rq,Eq (MMX) */ default: SUBIP(1); E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb()); diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h index 8ee2482..095f585 100644 --- a/src/cpu/core_16/support.h +++ b/src/cpu/core_16/support.h @@ -18,25 +18,13 @@ EAPoint IPPoint; - #define SUBIP(a) IPPoint-=a #define SETIP(a) IPPoint=SegBase(cs)+a #define GETIP (Bit16u)(IPPoint-SegBase(cs)) #define SAVEIP reg_ip=GETIP #define LOADIP IPPoint=SegBase(cs)+reg_ip -/* -#define ADDIP(a) { \ - Bit16u add_ip=(Bit16u)(IPPoint-SegBase(cs)); \ - add_ip+=a; \ - IPPoint=SegBase(cs)+add_ip; \ - } -*/ static INLINE void ADDIP(Bit16u add) { - -// Bit16u oldip=(IPPoint-SegBase(cs)); -// oldip+=add; -// IPPoint=SegBase(cs)+oldip; IPPoint=SegBase(cs)+((Bit16u)(((Bit16u)(IPPoint-SegBase(cs)))+(Bit16u)add)); } @@ -44,9 +32,6 @@ static INLINE void ADDIPFAST(Bit16s blah) { IPPoint+=blah; } -#define ERRORRETURN(a) { error_ret=a;goto errorreturn; } - - static INLINE Bit8u Fetchb() { Bit8u temp=LoadMb(IPPoint); IPPoint+=1; @@ -75,7 +60,6 @@ static INLINE Bit32s Fetchds() { return Fetchd(); } - static INLINE void Push_16(Bit16u blah) { reg_sp-=2; SaveMw(SegBase(ss)+reg_sp,blah); @@ -98,21 +82,15 @@ static INLINE Bit32u Pop_32() { return temp; }; - - - - - - #define stringDI \ EAPoint to; \ to=SegBase(es)+reg_di #define stringSI \ EAPoint from; \ - if (segprefix_on) { \ + if (prefixes & PREFIX_SEG) { \ from=(segprefix_base+reg_si); \ - SegPrefixReset; \ + PrefixReset; \ } else { \ from=SegBase(ds)+reg_si; \ } @@ -185,7 +163,3 @@ static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) { } -// if (flags.tf) { \ -// cpudecoder=CPU_Real_16_Slow_Decode_Special; \ -// return CBRET_NONE; \ -// } \ diff --git a/src/cpu/core_16/table_ea.h b/src/cpu/core_16/table_ea.h index a1d8655..c697269 100644 --- a/src/cpu/core_16/table_ea.h +++ b/src/cpu/core_16/table_ea.h @@ -21,25 +21,44 @@ typedef EAPoint (*GetEATable[256])(void); static GetEATable * lookupEATable; +#define PREFIX_NONE 0x0 +#define PREFIX_SEG 0x1 +#define PREFIX_ADDR 0x2 +#define PREFIX_SEG_ADDR 0x3 + + +static Bitu prefixes; static EAPoint segprefix_base; -static bool segprefix_on=false; + +/* Gets initialized at the bottem, can't seem to declare forward references */ +static GetEATable * EAPrefixTable[4]; + #define SegPrefix(blah) \ segprefix_base=SegBase(blah); \ - segprefix_on=true; \ - lookupEATable=&GetEA_16_s; \ + prefixes|=PREFIX_SEG; \ + lookupEATable=EAPrefixTable[prefixes]; \ goto restart; \ #define SegPrefix_66(blah) \ segprefix_base=SegBase(blah); \ - segprefix_on=true; \ - lookupEATable=&GetEA_16_s; \ + prefixes|=PREFIX_SEG; \ + lookupEATable=EAPrefixTable[prefixes]; \ goto restart_66; \ +#define PrefixReset \ + prefixes=PREFIX_NONE;lookupEATable=EAPrefixTable[PREFIX_NONE]; + +#define GetEADirect \ +EAPoint eaa;switch (prefixes) { \ +case PREFIX_NONE:eaa=SegBase(ds)+Fetchw();break; \ +case PREFIX_SEG:eaa=segprefix_base+Fetchw();PrefixReset;break; \ +case PREFIX_ADDR:eaa=SegBase(ds)+Fetchd();PrefixReset;break; \ +case PREFIX_SEG_ADDR:eaa=segprefix_base+Fetchd();PrefixReset;break; \ +} + -#define SegPrefixReset \ - segprefix_on=false;lookupEATable=&GetEA_16_n; /* The MOD/RM Decoder for EA for this decoder's addressing modes */ @@ -106,34 +125,34 @@ static GetEATable GetEA_16_n={ }; -#define prefixed(val) EAPoint ret=segprefix_base+val;SegPrefixReset;return ret; +#define segprefixed(val) EAPoint ret=segprefix_base+val;PrefixReset;return ret; -static EAPoint EA_16_00_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) } -static EAPoint EA_16_01_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) } -static EAPoint EA_16_02_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) } -static EAPoint EA_16_03_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) } -static EAPoint EA_16_04_s(void) { prefixed((Bit16u)(reg_si)) } -static EAPoint EA_16_05_s(void) { prefixed((Bit16u)(reg_di)) } -static EAPoint EA_16_06_s(void) { prefixed((Bit16u)(Fetchw())) } -static EAPoint EA_16_07_s(void) { prefixed((Bit16u)(reg_bx)) } +static EAPoint EA_16_00_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) } +static EAPoint EA_16_01_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) } +static EAPoint EA_16_02_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) } +static EAPoint EA_16_03_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) } +static EAPoint EA_16_04_s(void) { segprefixed((Bit16u)(reg_si)) } +static EAPoint EA_16_05_s(void) { segprefixed((Bit16u)(reg_di)) } +static EAPoint EA_16_06_s(void) { segprefixed((Bit16u)(Fetchw())) } +static EAPoint EA_16_07_s(void) { segprefixed((Bit16u)(reg_bx)) } -static EAPoint EA_16_40_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs())) } -static EAPoint EA_16_41_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs())) } -static EAPoint EA_16_42_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs())) } -static EAPoint EA_16_43_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs())) } -static EAPoint EA_16_44_s(void) { prefixed((Bit16u)(reg_si+Fetchbs())) } -static EAPoint EA_16_45_s(void) { prefixed((Bit16u)(reg_di+Fetchbs())) } -static EAPoint EA_16_46_s(void) { prefixed((Bit16u)(reg_bp+Fetchbs())) } -static EAPoint EA_16_47_s(void) { prefixed((Bit16u)(reg_bx+Fetchbs())) } +static EAPoint EA_16_40_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs())) } +static EAPoint EA_16_41_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs())) } +static EAPoint EA_16_42_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs())) } +static EAPoint EA_16_43_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs())) } +static EAPoint EA_16_44_s(void) { segprefixed((Bit16u)(reg_si+Fetchbs())) } +static EAPoint EA_16_45_s(void) { segprefixed((Bit16u)(reg_di+Fetchbs())) } +static EAPoint EA_16_46_s(void) { segprefixed((Bit16u)(reg_bp+Fetchbs())) } +static EAPoint EA_16_47_s(void) { segprefixed((Bit16u)(reg_bx+Fetchbs())) } -static EAPoint EA_16_80_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws())) } -static EAPoint EA_16_81_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws())) } -static EAPoint EA_16_82_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws())) } -static EAPoint EA_16_83_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws())) } -static EAPoint EA_16_84_s(void) { prefixed((Bit16u)(reg_si+Fetchws())) } -static EAPoint EA_16_85_s(void) { prefixed((Bit16u)(reg_di+Fetchws())) } -static EAPoint EA_16_86_s(void) { prefixed((Bit16u)(reg_bp+Fetchws())) } -static EAPoint EA_16_87_s(void) { prefixed((Bit16u)(reg_bx+Fetchws())) } +static EAPoint EA_16_80_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws())) } +static EAPoint EA_16_81_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws())) } +static EAPoint EA_16_82_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws())) } +static EAPoint EA_16_83_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws())) } +static EAPoint EA_16_84_s(void) { segprefixed((Bit16u)(reg_si+Fetchws())) } +static EAPoint EA_16_85_s(void) { segprefixed((Bit16u)(reg_di+Fetchws())) } +static EAPoint EA_16_86_s(void) { segprefixed((Bit16u)(reg_bp+Fetchws())) } +static EAPoint EA_16_87_s(void) { segprefixed((Bit16u)(reg_bx+Fetchws())) } static GetEATable GetEA_16_s={ /* 00 */ @@ -281,3 +300,117 @@ static GetEATable GetEA_32_n={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +INLINE EAPoint Sib_s(Bitu mode) { + Bit8u sib=Fetchb(); + EAPoint base; + switch (sib&7) { + case 0: /* EAX Base */ + base=segprefix_base+reg_eax;break; + case 1: /* ECX Base */ + base=segprefix_base+reg_ecx;break; + case 2: /* EDX Base */ + base=segprefix_base+reg_edx;break; + case 3: /* EBX Base */ + base=segprefix_base+reg_ebx;break; + case 4: /* ESP Base */ + base=segprefix_base+reg_esp;break; + case 5: /* #1 Base */ + if (!mode) { + base=segprefix_base+Fetchd();break; + } else { + base=segprefix_base+reg_ebp;break; + } + case 6: /* ESI Base */ + base=segprefix_base+reg_esi;break; + case 7: /* EDI Base */ + base=segprefix_base+reg_edi;break; + } + Bitu shift=sib >> 6; + switch ((sib >>3) &7) { + case 0: /* EAX Index */ + base+=(Bit32s)reg_eax<=8) return false; + if (flags.var2.b>8) return false; else return (flags.var1.b >> (8-flags.var2.b)) & 1; case t_SHLw: - if (flags.var2.b>=16) return false; + if (flags.var2.b>16) return false; else return (flags.var1.w >> (16-flags.var2.b)) & 1; case t_SHLd: - return (flags.var1.d >> (32 - flags.var2.b)) & 0x01; case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ - return (flags.var1.d >> (32 - flags.var2.b)) & 0x01; case t_DSHLd: - return (flags.var1.d >> (32 - flags.var2.b)) & 0x01; - + return (flags.var1.d >> (32 - flags.var2.b)) & 1; + case t_RCRb: case t_SHRb: - return (flags.var1.b >> (flags.var2.b - 1)) & 0x01; + return (flags.var1.b >> (flags.var2.b - 1)) & 1; + case t_RCRw: case t_SHRw: - return (flags.var1.w >> (flags.var2.b - 1)) & 0x01; + return (flags.var1.w >> (flags.var2.b - 1)) & 1; + case t_RCRd: case t_SHRd: - return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; - case t_SARb: - return (flags.var1.b >> (flags.var2.b - 1)) & 0x01; - case t_SARw: - return (flags.var1.w >> (flags.var2.b - 1)) & 0x01; - case t_SARd: - return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ - return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; case t_DSHRd: - return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; + return (flags.var1.d >> (flags.var2.b - 1)) & 1; + case t_SARb: + return (((Bit8s) flags.var1.b) >> (flags.var2.b - 1)) & 1; + case t_SARw: + return (((Bit16s) flags.var1.w) >> (flags.var2.b - 1)) & 1; + case t_SARd: + return (((Bit32s) flags.var1.d) >> (flags.var2.b - 1)) & 1; case t_NEGb: return (flags.var1.b!=0); case t_NEGw: @@ -107,29 +108,17 @@ bool get_CF(void) { case t_NEGd: return (flags.var1.d!=0); case t_ROLb: - return (flags.result.b & 1)>0; + return flags.result.b & 1; case t_ROLw: - return (flags.result.w & 1)>0; + return flags.result.w & 1; case t_ROLd: - return (flags.result.d & 1)>0; + return flags.result.d & 1; case t_RORb: return (flags.result.b & 0x80)>0; case t_RORw: return (flags.result.w & 0x8000)>0; case t_RORd: return (flags.result.d & 0x80000000)>0; - case t_RCLb: - return ((flags.var1.b >> (8-flags.var2.b))&1)>0; - case t_RCLw: - return ((flags.var1.w >> (16-flags.var2.b))&1)>0; - case t_RCLd: - return ((flags.var1.d >> (32-flags.var2.b))&1)>0; - case t_RCRb: - return ((flags.var1.b >> (flags.var2.b-1))&1)>0; - case t_RCRw: - return ((flags.var1.w >> (flags.var2.b-1))&1)>0; - case t_RCRd: - return ((flags.var1.d >> (flags.var2.b-1))&1)>0; case t_ORb: case t_ORw: case t_ORd: @@ -427,6 +416,9 @@ again: switch (type) { case t_UNKNOWN: case t_MUL: + case t_RCLb: + case t_RCLw: + case t_RCLd: return flags.of; case t_CF: type=flags.prev_type; @@ -448,9 +440,9 @@ again: case t_ADDd: case t_ADCd: //TODO fix dword Overflow - var1d31 = flags.var1.d & 0x8000; - var2d31 = flags.var2.d & 0x8000; - resultd31 = flags.result.d & 0x8000; + var1d31 = flags.var1.d & 0x80000000; + var2d31 = flags.var2.d & 0x80000000; + resultd31 = flags.result.d & 0x80000000; return (var1d31 == var2d31) && (resultd31 ^ var2d31); case t_SBBb: case t_SUBb: @@ -471,10 +463,10 @@ again: case t_SBBd: case t_SUBd: case t_CMPd: - var1d31 = flags.var1.d & 0x8000; - var2d31 = flags.var2.d & 0x8000; - resultd31 = flags.result.d & 0x8000; - return (var1d31 ^ var2d31) && (var1d31 ^ resultd31); + var1d31 = flags.var1.d & 0x80000000; + var2d31 = flags.var2.d & 0x80000000; + resultd31 = flags.result.d & 0x80000000; + return (var1d31 ^ var2d31) && (var1d31 ^ resultd31); case t_INCb: return (flags.result.b == 0x80); case t_INCw: @@ -494,39 +486,43 @@ again: case t_NEGd: return (flags.var1.d == 0x80000000); case t_ROLb: - case t_RORb: - case t_RCLb: - case t_RCRb: - case t_SHLb: - if (flags.var2.b==1) return ((flags.var1.b ^ flags.result.b) & 0x80) >0; - break; + return ((flags.result.b & 0x80) ^ (flags.result.b & 1 ? 0x80 : 0)) != 0; case t_ROLw: - case t_RORw: - case t_RCLw: - case t_RCRw: - case t_SHLw: - case t_DSHLw: //TODO This is euhm inccorect i think but let's keep it for now - if (flags.var2.b==1) return ((flags.var1.w ^ flags.result.w) & 0x8000) >0; - break; + return ((flags.result.w & 0x8000) ^ (flags.result.w & 1 ? 0x8000 : 0)) != 0; case t_ROLd: - case t_RORd: - case t_RCLd: - case t_RCRd: + return ((flags.result.d & 0x80000000) ^ (flags.result.d & 1 ? 0x80000000 : 0)) != 0; + case t_SHLb: + if (flags.var2.b>9) return false; + return ((flags.result.b & 0x80) ^ + ((flags.var1.b << (flags.var2.b - 1)) & 0x80)) != 0; + case t_SHLw: + if (flags.var2.b>17) return false; + return ((flags.result.w & 0x8000) ^ + ((flags.var1.w << (flags.var2.b - 1)) & 0x8000)) != 0; + case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ + return ((flags.result.w & 0x8000) ^ + (((flags.var1.d << (flags.var2.b - 1)) >> 16) & 0x8000)) != 0; case t_SHLd: case t_DSHLd: - if (flags.var2.b==1) return ((flags.var1.d ^ flags.result.d) & 0x80000000) >0; - break; + return ((flags.result.d & 0x80000000) ^ + ((flags.var1.d << (flags.var2.b - 1)) & 0x80000000)) != 0; + case t_RORb: + case t_RCRb: + return ((flags.result.b ^ (flags.result.b << 1)) & 0x80) > 0; + case t_RORw: + case t_RCRw: + case t_DSHRw: + return ((flags.result.w ^ (flags.result.w << 1)) & 0x8000) > 0; + case t_RORd: + case t_RCRd: + case t_DSHRd: + return ((flags.result.d ^ (flags.result.d << 1)) & 0x80000000) > 0; case t_SHRb: - if (flags.var2.b==1) return (flags.var1.b >= 0x80); - break; + return (flags.result.b >= 0x40); case t_SHRw: - case t_DSHRw: //TODO - if (flags.var2.b==1) return (flags.var1.w >= 0x8000); - break; + return (flags.result.w >= 0x4000); case t_SHRd: - case t_DSHRd: //TODO - if (flags.var2.b==1) return (flags.var1.d >= 0x80000000); - break; + return (flags.result.d >= 0x40000000); case t_SARb: case t_SARw: case t_SARd: diff --git a/src/cpu/slow_16.cpp b/src/cpu/slow_16.cpp index f681b85..c8d9a2d 100644 --- a/src/cpu/slow_16.cpp +++ b/src/cpu/slow_16.cpp @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #include "dosbox.h" #include "mem.h" #include "cpu.h" @@ -24,11 +25,12 @@ #include "pic.h" #include "fpu.h" +#if C_DEBUG +#include "debug.h" +#endif -typedef PhysOff EAPoint; - -#define SegBase(seg) Segs[seg].phys - +typedef PhysPt EAPoint; +#define SegBase(c) SegPhys(c) #define LoadMb(off) mem_readb(off) #define LoadMw(off) mem_readw(off) #define LoadMd(off) mem_readd(off) @@ -41,27 +43,6 @@ typedef PhysOff EAPoint; #define SaveMw(off,val) mem_writew(off,val) #define SaveMd(off,val) mem_writed(off,val) - -/* -typedef HostOff EAPoint; - -#define SegBase(seg) Segs[seg].host - -#define LoadMb(off) readb(off) -#define LoadMw(off) readw(off) -#define LoadMd(off) readd(off) - -#define LoadMbs(off) (Bit8s)(LoadMb(off)) -#define LoadMws(off) (Bit16s)(LoadMw(off)) -#define LoadMds(off) (Bit32s)(LoadMd(off)) - -#define SaveMb(off,val) writeb(off,val) -#define SaveMw(off,val) writew(off,val) -#define SaveMd(off,val) writed(off,val) - -*/ - - #define LoadRb(reg) reg #define LoadRw(reg) reg #define LoadRd(reg) reg @@ -72,17 +53,18 @@ typedef HostOff EAPoint; extern Bitu cycle_count; -#define CPU_386 -//TODO Change name -#define FULLFLAGS - +/* Enable parts of the cpu emulation */ +#define CPU_386 //Enable 386 instructions +#if C_FPU +#define CPU_FPU //Enable FPU escape instructions +#endif #include "core_16/support.h" static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count); static Bitu CPU_Real_16_Slow_Decode(Bitu count) { #include "core_16/start.h" while (count) { -#ifdef C_DEBUG +#if C_DEBUG cycle_count++; #endif count--; @@ -112,9 +94,10 @@ static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count) { void CPU_Real_16_Slow_Start(void) { - lookupEATable=&GetEA_16_n; - segprefix_base=0; - segprefix_on=false; cpudecoder=&CPU_Real_16_Slow_Decode; - + EAPrefixTable[0]=&GetEA_16_n; + EAPrefixTable[1]=&GetEA_16_s; + EAPrefixTable[2]=&GetEA_32_n; + EAPrefixTable[3]=&GetEA_32_s; + PrefixReset; }; diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index 2d800be..fdb66ac 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -18,9 +18,10 @@ #include +#include #include "dosbox.h" -#ifdef C_DEBUG +#if C_DEBUG #include "debug.h" #include "cpu.h" #include "video.h" @@ -35,22 +36,20 @@ #ifdef WIN32 void WIN32_Console(); #endif + 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; DBGBlock dbg; - static char input_line[256]; static Bitu input_count; Bitu cycle_count; - static bool debugging; - static void SetColor(bool test) { if (test) { if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));} @@ -58,22 +57,228 @@ static void SetColor(bool test) { if (has_colors()) { wattrset(dbg.win_reg,0);} } } -#define MAX_BREAKPOINT 10 -enum { BKPNT_REALMODE,BKPNT_PHYSICAL }; +struct SCodeViewData { + int cursorPos; + Bit16u firstInstSize; + Bit16u useCS; + Bit32u useEIPlast, useEIPmid; + Bit32u useEIP; + Bit16u cursorSeg; + Bit32u cursorOfs; + bool inputMode; + char inputStr[255]; -struct BreakPoint { - PhysOff location; - Bit8u olddata; - Bit16u seg; - Bit16u off_16; - Bit32u off_32; - Bit8u type; - bool enabled; - bool active; +} codeViewData; + +static Bit16u dataSeg,dataOfs; + +/********************/ +/* Breakpoint stuff */ +/********************/ + +enum { BKPNT_REALMODE, 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 BPoints; + +static bool IsBreakpoint(PhysPt off) +{ + // iterate list and remove TBreakpoint + std::list::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); i++) { + if (((*i).type==BKPNT_PHYSICAL) && ((*i).location==off)) return true; + } + return false; }; -BreakPoint bpoints[MAX_BREAKPOINT]; +/* This clears all breakpoints by replacing their 0xcc by the original byte */ +static void ClearBreakpoints(void) +{ + // iterate list and place 0xCC + std::list::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::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::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); i++) { + if (((*i).type==BKPNT_PHYSICAL) && (*i).enabled) { + Bit8u data = mem_readb((*i).location); + if (data!=0xCC) { + (*i).olddata = data; + (*i).active = true; + mem_writeb((*i).location,0xCC); + } + }; + } +} + +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); +}; + +static bool RemoveBreakpoint(PhysPt off) +{ + // iterate list and remove TBreakpoint + std::list::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); i++) { + if (((*i).type==BKPNT_PHYSICAL) && ((*i).location==off)) { + TBreakpoint* bp = &(*i); + if ((*i).active && (mem_readb((*i).location)==0xCC)) mem_writeb((*i).location,(*i).olddata); + (*i).active = false; + if ((*i).once) (BPoints.erase)(i); + + return true; + }; + } + return false; +}; + +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(); + debugging=false; + DrawCode(); + DOSBOX_SetNormalLoop(); + return true; + } + 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::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); ++i) { + if ((*i).active && (*i).enabled) { + if ((*i).location==where) { + found=true; + break; + } + } + } + if (!found) return false; + RemoveBreakpoint(where); + ClearBreakpoints(); + reg_eip -= 1; + DEBUG_Enable(); + return true; +} + +bool DEBUG_IntBreakpoint(Bit8u intNum) +{ + PhysPt where=SegPhys(cs)+reg_eip-2; + bool found=false; + std::list::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); ++i) { + if ( ((*i).type==BKPNT_INTERRUPT) && (*i).enabled) { + if (((*i).olddata==intNum) && ( ((*i).ahValue==(Bit16u)reg_ah) || ((*i).ahValue==BPINT_ALL)) ) { + if ((*i).active) { + found=true; + (*i).active=false; + //(BPoints.erase)(i); + //break; + } else { + // One step over is ok -> activate for next occurence + (*i).active=true; + //break; + } + } + } + } + if (!found) return false; + + // Remove normal breakpoint here, cos otherwise 0xCC wont be removed here + RemoveBreakpoint(where); + ClearBreakpoints(); + reg_eip -= 2; + DEBUG_Enable(); + return true; +}; + +/********************/ +/* Draw windows */ +/********************/ + +static void DrawData(void) { + + Bit16u add = dataOfs; + /* Data win */ + for (int y=0; y<8; y++) { + // Adress + mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add); + for (int x=0; x<16; x++) { + Bit8u ch = real_readb(dataSeg,add); + mvwprintw (dbg.win_data,1+y,11+3*x,"%02X",ch); + if (ch<32) ch='.'; + mvwprintw (dbg.win_data,1+y,60+x,"%c",ch); + add++; + }; + } + wrefresh(dbg.win_data); +}; static void DrawRegisters(void) { /* Main Registers */ @@ -88,12 +293,12 @@ static void DrawRegisters(void) { SetColor(reg_esp!=oldregs.esp);oldregs.esp=reg_esp;mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp); SetColor(reg_eip!=oldregs.eip);oldregs.eip=reg_eip;mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip); - SetColor(Segs[ds].value!=oldsegs[ds].value);oldsegs[ds].value=Segs[ds].value;mvwprintw (dbg.win_reg,0,31,"%04X",Segs[ds].value); - SetColor(Segs[es].value!=oldsegs[es].value);oldsegs[es].value=Segs[es].value;mvwprintw (dbg.win_reg,0,41,"%04X",Segs[es].value); - SetColor(Segs[fs].value!=oldsegs[fs].value);oldsegs[fs].value=Segs[fs].value;mvwprintw (dbg.win_reg,0,51,"%04X",Segs[fs].value); - SetColor(Segs[gs].value!=oldsegs[gs].value);oldsegs[gs].value=Segs[gs].value;mvwprintw (dbg.win_reg,0,61,"%04X",Segs[gs].value); - SetColor(Segs[ss].value!=oldsegs[ss].value);oldsegs[ss].value=Segs[ss].value;mvwprintw (dbg.win_reg,0,71,"%04X",Segs[ss].value); - SetColor(Segs[cs].value!=oldsegs[cs].value);oldsegs[cs].value=Segs[cs].value;mvwprintw (dbg.win_reg,1,31,"%04X",Segs[cs].value); + SetColor(SegValue(ds)!=oldsegs[ds].val);oldsegs[ds].val=SegValue(ds);mvwprintw (dbg.win_reg,0,31,"%04X",SegValue(ds)); + SetColor(SegValue(es)!=oldsegs[es].val);oldsegs[es].val=SegValue(es);mvwprintw (dbg.win_reg,0,41,"%04X",SegValue(es)); + SetColor(SegValue(fs)!=oldsegs[fs].val);oldsegs[fs].val=SegValue(fs);mvwprintw (dbg.win_reg,0,51,"%04X",SegValue(fs)); + SetColor(SegValue(gs)!=oldsegs[gs].val);oldsegs[gs].val=SegValue(gs);mvwprintw (dbg.win_reg,0,61,"%04X",SegValue(gs)); + SetColor(SegValue(ss)!=oldsegs[ss].val);oldsegs[ss].val=SegValue(ss);mvwprintw (dbg.win_reg,0,71,"%04X",SegValue(ss)); + SetColor(SegValue(cs)!=oldsegs[cs].val);oldsegs[cs].val=SegValue(cs);mvwprintw (dbg.win_reg,1,31,"%04X",SegValue(cs)); /*Individual flags*/ @@ -114,76 +319,269 @@ static void DrawRegisters(void) { wrefresh(dbg.win_reg); }; - -static void DrawCode(void) { - PhysOff start=Segs[cs].phys+reg_eip; +static void DrawCode(void) +{ + Bit32u disEIP = codeViewData.useEIP; + PhysPt start = codeViewData.useCS*16 + codeViewData.useEIP; char dline[200];Bitu size;Bitu c; + for (Bit32u i=0;i<10;i++) { -// size=DEBUG_Disasm(start,false,dline); - size=DasmI386(dline, start, reg_eip, false); - mvwprintw(dbg.win_code,i,0,"%02X:%04X ",Segs[cs].value,(start-Segs[cs].phys)); + if (has_colors()) { + if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) { + wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK)); + if (codeViewData.cursorPos==-1) { + codeViewData.cursorPos = i; // Set Cursor + codeViewData.cursorSeg = SegValue(cs); + codeViewData.cursorOfs = disEIP; + } + } else if (i == codeViewData.cursorPos) { + wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY)); + codeViewData.cursorSeg = codeViewData.useCS; + codeViewData.cursorOfs = disEIP; + } else if (IsBreakpoint(start)) { + wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED)); + } else { + wattrset(dbg.win_code,0); + } + } + + size=DasmI386(dline, start, disEIP, false); + mvwprintw(dbg.win_code,i,0,"%04X:%04X ",codeViewData.useCS,disEIP); for (c=0;c=size*2;c--) waddch(dbg.win_code,' '); waddstr(dbg.win_code,dline); for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' '); start+=size; + disEIP+=size; + + if (i==0) codeViewData.firstInstSize = size; + if (i==4) codeViewData.useEIPmid = disEIP; } + + codeViewData.useEIPlast = disEIP; + + wattrset(dbg.win_code,0); + if (!debugging) { + mvwprintw(dbg.win_code,10,0,"(Running)",codeViewData.inputStr); + } else if (codeViewData.inputMode) { + mvwprintw(dbg.win_code,10,0,"-> %s_ ",codeViewData.inputStr); + } else { + mvwprintw(dbg.win_code,10,0," "); + for (c=0;c<50;c++) waddch(dbg.win_code,' '); + }; + wrefresh(dbg.win_code); } -/* This clears all breakpoints by replacing their 0xcc by the original byte */ -static void ClearBreakPoints(void) { - for (Bit32u i=0;i=codeViewData.useEIP) && (reg_eip<=codeViewData.useEIPlast)) { + // in valid window - scroll ? + if (reg_eip>=codeViewData.useEIPmid) codeViewData.useEIP += codeViewData.firstInstSize; + + } else { + // totally out of range. + codeViewData.useCS = SegValue(cs); + codeViewData.useEIP = reg_eip; } -} + codeViewData.cursorPos = -1; // Recalc Cursor position +}; -static void SetBreakPoints(void) { - for (Bit32u i=0;i='0') && (*hex<='9')) value = (value<<4)+*hex-'0'; else + if ((*hex>='A') && (*hex<='F')) value = (value<<4)+*hex-'A'+10; + else break; // No valid char + hex++; + }; + return value; +}; + +bool ParseCommand(char* str) +{ + char* found = str; + while (*found) *found++=toupper(*found); + found = strstr(str,"BP "); + if (found) { // Add new breakpoint + found+=3; + Bit16u seg = GetHexValue(found,found);found++; // skip ":" + Bit32u ofs = GetHexValue(found,found); + AddBreakpoint(seg,ofs,false); + LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs); + return true; } -} + found = strstr(str,"BPINT"); + if (found) { // Add Interrupt Breakpoint + found+=5; + Bit8u intNr = GetHexValue(found,found); found++; + Bit8u valAH = GetHexValue(found,found); + if ((valAH==0x00) && (*found=='*')) { + AddIntBreakpoint(intNr,BPINT_ALL,false); + LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X",intNr); + } else { + AddIntBreakpoint(intNr,valAH,false); + LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH); + } + return true; + } + found = strstr(str,"BPLIST"); + if (found) { + wprintw(dbg.win_out,"Breakpoint list:\n"); + wprintw(dbg.win_out,"-------------------------------------------------------------------------\n"); + Bit32u nr = 0; + // iterate list + std::list::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); i++) { + if ((*i).type==BKPNT_PHYSICAL) { + wprintw(dbg.win_out,"%02X. BP %04X:%04X\n",nr,(*i).segment,(*i).offset); + nr++; + } else if ((*i).type==BKPNT_INTERRUPT) { + if ((*i).ahValue==BPINT_ALL) wprintw(dbg.win_out,"%02X. BPINT %02X\n",nr,(*i).olddata); + else wprintw(dbg.win_out,"%02X. BPINT %02X AH=%02X\n",nr,(*i).olddata,(*i).ahValue); + nr++; + }; + } + wrefresh(dbg.win_out); + return true; + }; - - -static void AddBreakPoint(PhysOff off) { - -} - - - -bool DEBUG_BreakPoint(void) { - /* First get the phyiscal address and check for a set breakpoint */ - PhysOff where=real_phys(Segs[cs].value,reg_ip-1); - bool found=false; - for (Bit32u i=0;i::iterator i; + for(i=BPoints.begin(); i != BPoints.end(); i++) { + if ((*i).type==BKPNT_PHYSICAL) { + if (nr==bpNr) { + DeleteBreakpoint((*i).location); + LOG_DEBUG("DEBUG: Breakpoint %02X deleted.",nr); + break; + } + nr++; + } else if ((*i).type==BKPNT_INTERRUPT) { + if (nr==bpNr) { + (BPoints.erase)(i); + LOG_DEBUG("DEBUG: Breakpoint %02X. deleted.",nr); + break;; + } + nr++; + } } } + return true; + } + found = strstr(str,"C "); + if (found) { // Set code overview + found++; + Bit16u codeSeg = GetHexValue(found,found); found++; + Bit32u codeOfs = GetHexValue(found,found); + LOG_DEBUG("DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs); + codeViewData.useCS = codeSeg; + codeViewData.useEIP = codeOfs; + return true; + } + found = strstr(str,"D "); + if (found) { // Set data overview + found++; + dataSeg = GetHexValue(found,found); found++; + dataOfs = GetHexValue(found,found); + LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); + return true; + } + if ((*str=='H') || (*str=='?')) { + wprintw(dbg.win_out,"Debugger keys:\n"); + wprintw(dbg.win_out,"--------------------------------------------------------------------------\n"); + wprintw(dbg.win_out,"F5 - Run\n"); + wprintw(dbg.win_out,"F9 - Set/Remove breakpoint\n"); + wprintw(dbg.win_out,"F10/F11 - Step over / trace into instruction\n"); + wprintw(dbg.win_out,"Up/Down - Move code view cursor\n"); + wprintw(dbg.win_out,"Return - Enable command line input\n"); + wprintw(dbg.win_out,"D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX\n"); + wprintw(dbg.win_out,"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"); + wprintw(dbg.win_out,"BPINT [intNr] * - Set interrupt breakpoint\n"); + wprintw(dbg.win_out,"BPINT [intNr] [ah] - Set interrupt breakpoint with ah\n"); + 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,"H - Help\n"); + wrefresh(dbg.win_out); + return TRUE; } - if (!found) return false; - ClearBreakPoints(); - DEBUG_Enable(); - - SetBreakPoints(); return false; -} - - - +}; Bit32u DEBUG_CheckKeys(void) { + + if (codeViewData.inputMode) { + int key = getch(); + if (key>0) { + switch (key) { + case 0x0A: codeViewData.inputMode = FALSE; + ParseCommand(codeViewData.inputStr); + break; + case 0x08: // delete + if (strlen(codeViewData.inputStr)>0) codeViewData.inputStr[strlen(codeViewData.inputStr)-1] = 0; + break; + default : if ((key>=32) && (key<=128) && (strlen(codeViewData.inputStr)<253)) { + Bit32u len = strlen(codeViewData.inputStr); + codeViewData.inputStr[len] = char(key); + codeViewData.inputStr[len+1] = 0; + } + break; + } + DEBUG_DrawScreen(); + } + return 0; + }; + int key=getch(); Bit32u ret=0; if (key>0) { - switch (key) { + switch (toupper(key)) { case '1': ret=(*cpudecoder)(100); break; @@ -202,32 +600,102 @@ Bit32u DEBUG_CheckKeys(void) { case 'q': ret=(*cpudecoder)(5); break; + case 'D': dataSeg = SegValue(ds); + dataOfs = reg_si; + break; + case 'E': dataSeg = SegValue(es); + dataOfs = reg_di; + break; + case 'X': dataSeg = SegValue(ds); + dataOfs = reg_dx; + break; + case 'B': dataSeg = SegValue(es); + dataOfs = reg_bx; + break; + case 'S': dataSeg = SegValue(ss); + dataOfs = reg_sp; + break; - default: - ret=(*cpudecoder)(1); + case 'R' : dataOfs -= 16; break; + case 'F' : dataOfs += 16; break; + case 'H' : strcpy(codeViewData.inputStr,"H "); + ParseCommand(codeViewData.inputStr); + break; + + case 0x0A : // Return : input + codeViewData.inputMode = true; + codeViewData.inputStr[0] = 0; + break; + case KEY_DOWN: // down + if (codeViewData.cursorPos<9) codeViewData.cursorPos++; + else codeViewData.useEIP += codeViewData.firstInstSize; + break; + case KEY_UP: // up + if (codeViewData.cursorPos>0) codeViewData.cursorPos--; + else codeViewData.useEIP -= 1; + break; + case KEY_F(5): // Run Programm + debugging=false; + SetBreakpoints(); + 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); + } + break; + case KEY_F(10): // Step over inst + if (StepOver()) return 0; + else { + Bitu ret=(*cpudecoder)(1); + SetCodeWinStart(); + } + break; + case KEY_F(11): // trace into + ret = (*cpudecoder)(1); + SetCodeWinStart(); + break; + +// default: +// // FIXME : Is this correct ? +// if (key<0x200) ret=(*cpudecoder)(1); +// break; }; DEBUG_DrawScreen(); } return ret; }; - Bitu DEBUG_Loop(void) { //TODO Disable sound GFX_Events(); + // Interrupt started ? - then skip it + Bit16u oldCS = SegValue(cs); + Bit32u oldEIP = reg_eip; PIC_runIRQs(); + if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) { + AddBreakpoint(oldCS,oldEIP,true); + SetBreakpoints(); + debugging=false; + DOSBOX_SetNormalLoop(); + return 0; + } + return DEBUG_CheckKeys(); } void DEBUG_Enable(void) { - DEBUG_DrawScreen(); debugging=true; + SetCodeWinStart(); + DEBUG_DrawScreen(); DOSBOX_SetLoop(&DEBUG_Loop); } void DEBUG_DrawScreen(void) { DrawRegisters(); + DrawData(); DrawCode(); } static void DEBUG_RaiseTimerIrq(void) { @@ -248,5 +716,10 @@ void DEBUG_Init(void) { /* 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)(); } -#endif \ No newline at end of file + +#endif + diff --git a/src/debug/debug_disasm.cpp b/src/debug/debug_disasm.cpp index 78aa210..42cd96d 100644 --- a/src/debug/debug_disasm.cpp +++ b/src/debug/debug_disasm.cpp @@ -63,7 +63,7 @@ Any comments/updates/bug reports to: */ #include "dosbox.h" -#ifdef C_DEBUG +#if C_DEBUG #include #include #include @@ -456,7 +456,7 @@ static char *addr_to_hex(UINT32 addr, int splitup) { return buffer; } -static PhysOff getbyte_mac; +static PhysPt getbyte_mac; static UINT8 getbyte(void) { @@ -1070,7 +1070,7 @@ static void ua_str(char *str) } -Bitu DasmI386(char* buffer, PhysOff pc, Bitu cur_ip, bool bit32) +Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32) { Bitu c; diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index c13f306..dadc282 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -19,7 +19,7 @@ #include "dosbox.h" -#ifdef C_DEBUG +#if C_DEBUG #include #include @@ -96,8 +96,8 @@ static void MakeSubWindows(void) { dbg.win_data=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0); outy+=11; /* The Code Window */ - dbg.win_code=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0); - outy+=11; + dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0); + outy+=12; /* The output Window */ dbg.win_out=subwin(dbg.win_main,dbg.win_main->_maxy-outy-1,dbg.win_main->_maxx,outy,0); dbg.input_y=dbg.win_main->_maxy-1; @@ -110,6 +110,9 @@ static void MakeSubWindows(void) { static void MakePairs(void) { init_pair(PAIR_BLACK_BLUE, COLOR_BLACK, COLOR_CYAN); init_pair(PAIR_BYELLOW_BLACK, COLOR_YELLOW /*| FOREGROUND_INTENSITY */, COLOR_BLACK); + init_pair(PAIR_GREEN_BLACK, COLOR_GREEN /*| FOREGROUND_INTENSITY */, COLOR_BLACK); + init_pair(PAIR_BLACK_GREY, COLOR_BLACK /*| FOREGROUND_INTENSITY */, COLOR_WHITE); + init_pair(PAIR_GREY_RED, COLOR_WHITE/*| FOREGROUND_INTENSITY */, COLOR_RED); } diff --git a/src/debug/debug_inc.h b/src/debug/debug_inc.h index f7276a7..e77806d 100644 --- a/src/debug/debug_inc.h +++ b/src/debug/debug_inc.h @@ -22,11 +22,14 @@ #define PAIR_BLACK_BLUE 1 #define PAIR_BYELLOW_BLACK 2 +#define PAIR_GREEN_BLACK 3 +#define PAIR_BLACK_GREY 4 +#define PAIR_GREY_RED 5 void DBGUI_StartUp(void); -struct DBGBlock { +struct DBGBlock { WINDOW * win_main; /* The Main Window */ WINDOW * win_reg; /* Register Window */ WINDOW * win_data; /* Data Output window */ @@ -40,7 +43,7 @@ struct DBGBlock { struct DASMLine { Bit32u pc; char dasm[80]; - PhysOff ea; + PhysPt ea; Bit16u easeg; Bit32u eaoff; }; @@ -49,4 +52,4 @@ extern DBGBlock dbg; /* Local Debug Stuff */ -Bitu DasmI386(char* buffer, PhysOff pc, Bitu cur_ip, bool bit32); +Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32); diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index 003c15e..77998e2 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.h @@ -63,21 +63,13 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { extern void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page); bool device_CON::Write(Bit8u * data,Bit16u * size) { -//TODO Hack a way to call int 0x10 - Bit16u oldax=reg_ax;Bit16u oldbx=reg_bx; Bit16u count=0; while (*size>count) { -/* - reg_al=data[count]; - reg_ah=0x0e; - reg_bx=0x0007; - CALLBACK_RunRealInt(0x10); -*/ + INT10_TeletypeOutput(data[count],7,false,0); count++; } *size=count; -// reg_ax=oldax;reg_bx=oldbx; return true; } diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 4a93f32..c334de4 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -29,6 +29,8 @@ #include "dos_inc.h" DOS_Block dos; +DOS_InfoBlock dosInfoBlock; + static Bit8u dos_copybuf[0x10000]; static Bitu call_20,call_21,call_theend; @@ -105,7 +107,7 @@ static Bitu DOS_21Handler(void) { case 0x09: /* Write string to STDOUT */ { Bit8u c;Bit16u n=1; - PhysOff buf=real_phys(Segs[ds].value,reg_dx); + PhysPt buf=SegPhys(ds)+reg_dx; while ((c=mem_readb(buf++))!='$') { DOS_WriteFile(STDOUT,&c,&n); } @@ -114,18 +116,16 @@ static Bitu DOS_21Handler(void) { case 0x0a: /* Buffered Input */ { //TODO ADD Break checkin in STDIN but can't care that much for it - PhysOff data=real_phys(Segs[ds].value,reg_dx); + PhysPt data=SegPhys(ds)+reg_dx; Bit8u free=mem_readb(data); Bit8u read=0;Bit8u c;Bit16u n=1; if (!free) break; while (readm,(PhysPt)&(((s *)0)->m)) +#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val) - -class DOS_PSP { +class MemStruct { public: - DOS_PSP(Bit16u segment); + 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 MakeNew(Bit16u env,Bit16u memsize); - - - Bit16u base_seg; private: - PhysOff off; +PhysPt pt; + }; -DOS_PSP::DOS_PSP(Bit16u segment) { - base_seg=segment; - off=Real2Phys(RealMake(segment,0)); + +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); + +private: + Bit16u seg; + PhysPt pt; }; -void DOS_PSP::MakeNew(Bit16u env,Bit16u next_para) { +void DOS_PSP::NewPt(Bit16u segment) { + seg=segment; + pt=PhysMake(segment,0); +}; + + + +void DOS_PSP::MakeNew(Bit16u mem_size) { Bitu i; - for (i=0;i<256;i++) mem_writeb(off+i,0); -/* Standard blocks */ - mem_writeb(off+offsetof(sPSP,exit[0]),0xcd); - mem_writeb(off+offsetof(sPSP,exit[1]),0x20); - - mem_writeb(off+offsetof(sPSP,service[0]),0xcd); - mem_writeb(off+offsetof(sPSP,service[1]),0x21); - mem_writeb(off+offsetof(sPSP,service[2]),0xcb); - - mem_writew(off+offsetof(sPSP,next_seg),next_para); - - -// mem_writew(off+offsetof(sPSP,psp_parent),dos.psp->base_seg); - - /* Setup initial file table */ - mem_writed(off+offsetof(sPSP,int_22),RealGetVec(0x22)); - mem_writed(off+offsetof(sPSP,int_23),RealGetVec(0x23)); - mem_writed(off+offsetof(sPSP,int_24),RealGetVec(0x24)); - - -#if 0 - - newpsp->mem_size=prevpsp->mem_size; - newpsp->environment=0; - - newpsp->int_22.full=real_getvec(0x22); - newpsp->int_23.full=real_getvec(0x23); - newpsp->int_24.full=real_getvec(0x24); - - newpsp->psp_parent=dos.psp; - newpsp->prev_psp.full=0xFFFFFFFF; - - Bit32u i; - Bit8u * prevfile=real_off(prevpsp->file_table.seg,prevpsp->file_table.off); - for (i=0;i<20;i++) newpsp->files[i]=prevfile[i]; - - newpsp->max_files=20; - newpsp->file_table.seg=pspseg; - newpsp->file_table.off=offsetof(PSP,files); - /* Save the old DTA in this psp */ - newpsp->dta.seg=dos.dta.seg; - newpsp->dta.off=dos.dta.off; - /* Setup the DTA */ - dos.dta.seg=pspseg; - dos.dta.off=0x80; - return; -#endif - + /* Clear it first */ + for (i=0;i<256;i++) mem_writeb(pt+i,0); + /* 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); + sSave(sPSP,service[1],0x21); + sSave(sPSP,service[2],0xcb); + /* psp and psp-parent */ + 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); + /* Process DTA */ + sSave(sPSP,dta,RealMake(seg,128)); + /* User Stack pointer */ + //Copy from previous psp + // mem_writed(pt+offsetof(sPSP,stack), + /* 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); + } } +Bit8u DOS_PSP::GetFileHandle(Bitu 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(FCB,drive),a); + mem_writeb(off+offsetof(sFCB,drive)+FCB_EXTENDED,a); } void DOS_FCB::Set_filename(char * a){ - MEM_BlockWrite(off+offsetof(FCB,filename),a,8); + MEM_BlockWrite(off+offsetof(sFCB,filename)+FCB_EXTENDED,a,8); } void DOS_FCB::Set_ext(char * a) { - MEM_BlockWrite(off+offsetof(FCB,ext),a,3); + MEM_BlockWrite(off+offsetof(sFCB,ext)+FCB_EXTENDED,a,3); } void DOS_FCB::Set_current_block(Bit16u a){ - mem_writew(off+offsetof(FCB,current_block),a); + mem_writew(off+offsetof(sFCB,current_block)+FCB_EXTENDED,a); } void DOS_FCB::Set_record_size(Bit16u a){ - mem_writew(off+offsetof(FCB,record_size),a); + mem_writew(off+offsetof(sFCB,record_size)+FCB_EXTENDED,a); } void DOS_FCB::Set_filesize(Bit32u a){ - mem_writed(off+offsetof(FCB,filesize),a); + mem_writed(off+offsetof(sFCB,filesize)+FCB_EXTENDED,a); } void DOS_FCB::Set_date(Bit16u a){ - mem_writew(off+offsetof(FCB,date),a); + mem_writew(off+offsetof(sFCB,date)+FCB_EXTENDED,a); } void DOS_FCB::Set_time(Bit16u a){ - mem_writew(off+offsetof(FCB,time),a); + mem_writew(off+offsetof(sFCB,time)+FCB_EXTENDED,a); } Bit8u DOS_FCB::Get_drive(void){ - return mem_readb(off+offsetof(FCB,drive)); + return mem_readb(off+offsetof(sFCB,drive)+FCB_EXTENDED); } void DOS_FCB::Get_filename(char * a){ - MEM_BlockRead(off+offsetof(FCB,filename),a,8); + MEM_BlockRead(off+offsetof(sFCB,filename)+FCB_EXTENDED,a,8); } void DOS_FCB::Get_ext(char * a){ - MEM_BlockRead(off+offsetof(FCB,ext),a,3); + MEM_BlockRead(off+offsetof(sFCB,ext)+FCB_EXTENDED,a,3); } Bit16u DOS_FCB::Get_current_block(void){ - return mem_readw(off+offsetof(FCB,current_block)); + return mem_readw(off+offsetof(sFCB,current_block)+FCB_EXTENDED); } Bit16u DOS_FCB::Get_record_size(void){ - return mem_readw(off+offsetof(FCB,record_size)); + return mem_readw(off+offsetof(sFCB,record_size)+FCB_EXTENDED); } Bit32u DOS_FCB::Get_filesize(void){ - return mem_readd(off+offsetof(FCB,filesize)); + return mem_readd(off+offsetof(sFCB,filesize)+FCB_EXTENDED); } Bit16u DOS_FCB::Get_date(void){ - return mem_readw(off+offsetof(FCB,date)); + return mem_readw(off+offsetof(sFCB,date)+FCB_EXTENDED); } Bit16u DOS_FCB::Get_time(void){ - return mem_readw(off+offsetof(FCB,time)); + return mem_readw(off+offsetof(sFCB,time)+FCB_EXTENDED); } + + +void DOS_ParamBlock::InitExec(RealPt cmdtail) { + mem_writew(off+offsetof(sParamBlock,exec.envseg),0); + mem_writed(off+offsetof(sParamBlock,exec.fcb1),0); + mem_writed(off+offsetof(sParamBlock,exec.fcb2),0); + mem_writed(off+offsetof(sParamBlock,exec.cmdtail),cmdtail); +} + +Bit16u DOS_ParamBlock::loadseg(void) { + return mem_readw(off+offsetof(sParamBlock,overlay.loadseg)); +} +Bit16u DOS_ParamBlock::relocation(void){ + return mem_readw(off+offsetof(sParamBlock,overlay.loadseg)); +} +Bit16u DOS_ParamBlock::envseg(void){ + return mem_readw(off+offsetof(sParamBlock,exec.envseg)); +} +RealPt DOS_ParamBlock::initsssp(void){ + return mem_readd(off+offsetof(sParamBlock,exec.initsssp)); +} +RealPt DOS_ParamBlock::initcsip(void){ + return mem_readd(off+offsetof(sParamBlock,exec.initcsip)); +} +RealPt DOS_ParamBlock::fcb1(void){ + return mem_readd(off+offsetof(sParamBlock,exec.fcb1)); +} +RealPt DOS_ParamBlock::fcb2(void){ + return mem_readd(off+offsetof(sParamBlock,exec.fcb2)); +} +RealPt DOS_ParamBlock::cmdtail(void){ + return mem_readd(off+offsetof(sParamBlock,exec.cmdtail)); +} + +// * Dos Info Block (list of lists) * + +void DOS_InfoBlock::SetLocation(Bit16u segment) +{ + seg = segment; + dib = (SDosInfoBlock*)HostMake(segment,0); + Bit16u size = sizeof(SDosInfoBlock); + memset(dib,0,sizeof(SDosInfoBlock)); +}; + +void DOS_InfoBlock::SetFirstMCB(RealPt pt) +{ + dib->firstMCB = pt; +}; + +void DOS_InfoBlock::GetDIBPointer(Bit16u& segment, Bit16u& offset) +{ + segment = seg; + offset = offsetof(SDosInfoBlock,firstDPB); +}; diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index fd3fb54..9cb7796 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -21,8 +21,9 @@ #include "mem.h" #include "dos_inc.h" #include "cpu.h" +#if defined (_MSC_VER) #pragma pack(1) - +#endif struct EXE_Header { @@ -40,8 +41,13 @@ struct EXE_Header { Bit16u initCS; Bit16u reloctable; Bit16u overlay; -}; +} +#if defined (_MSC_VER) +; #pragma pack() +#else +__attribute__ ((packed)); +#endif #define MAGIC1 0x5a4d #define MAGIC2 0x4d5a @@ -58,7 +64,7 @@ struct EXE_Header { bool DOS_Terminate(bool tsr) { - PSP * psp=(PSP *)real_off(dos.psp,0); + PSP * psp=(PSP *)HostMake(dos.psp,0); if (!tsr) { /* Free Files owned by process */ for (Bit16u i=0;imax_files;i++) { @@ -67,16 +73,16 @@ bool DOS_Terminate(bool tsr) { DOS_FreeProcessMemory(dos.psp); }; dos.psp=psp->psp_parent; - PSP * oldpsp=(PSP *)real_off(dos.psp,0); + 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); - SetSegment_16(cs,RealSeg(old22)); + SegSet16(cs,RealSeg(old22)); reg_ip=RealOff(old22); /* Restore the SS:SP to the previous one */ - SetSegment_16(ss,RealSeg(oldpsp->stack)); + SegSet16(ss,RealSeg(oldpsp->stack)); reg_sp=RealOff(oldpsp->stack); /* Restore interrupt 22,23,24 */ RealSetVec(0x22,psp->int_22); @@ -91,17 +97,17 @@ 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 *)real_off(dos.psp,0); + PSP * psp=(PSP *)HostMake(dos.psp,0); Bit8u * envread,*envwrite; Bit16u envsize=1; bool parentenv=true; if (*segment==0) { if (!psp->environment) parentenv=false; //environment seg=0 - envread=real_off(psp->environment,0); + envread=HostMake(psp->environment,0); } else { if (!*segment) parentenv=false; //environment seg=0 - envread=real_off(*segment,0); + envread=HostMake(*segment,0); } //TODO Make a good DOS first psp @@ -117,7 +123,7 @@ static bool MakeEnv(char * name,Bit16u * segment) { } Bit16u size=long2para(envsize+ENV_KEEPFREE); if (!DOS_AllocateMemory(segment,&size)) return false; - envwrite=real_off(*segment,0); + envwrite=HostMake(*segment,0); if (parentenv) { bmemcpy(envwrite,envread,envsize); envwrite+=envsize; @@ -127,12 +133,12 @@ static bool MakeEnv(char * name,Bit16u * segment) { *((Bit16u *) envwrite)=1; envwrite+=2; //TODO put the filename here - return DOS_Canonicalize(name,envwrite); + return DOS_Canonicalize(name,(char *)envwrite); }; bool DOS_NewPSP(Bit16u pspseg) { - PSP * newpsp=(PSP *)real_off(pspseg,0); - PSP * prevpsp=(PSP *)real_off(dos.psp,0); + 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; @@ -163,11 +169,11 @@ bool DOS_NewPSP(Bit16u pspseg) { static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { - PSP * psp=(PSP *)real_off(pspseg,0); + PSP * psp=(PSP *)HostMake(pspseg,0); /* Fix the PSP index of this MCB */ - MCB * pspmcb=(MCB *)real_off(pspseg-1,0); + MCB * pspmcb=(MCB *)HostMake(pspseg-1,0); pspmcb->psp_segment=pspseg; - MCB * envmcb=(MCB *)real_off(envseg-1,0); + MCB * envmcb=(MCB *)HostMake(envseg-1,0); envmcb->psp_segment=pspseg; memset((void *)psp,0,sizeof(PSP)); @@ -204,7 +210,7 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { } static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) { - PSP * psp=(PSP *)real_off(pspseg,0); + PSP * psp=(PSP *)HostMake(pspseg,0); if (block->exec.cmdtail) { memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128); @@ -226,7 +232,7 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) { Bit16u envseg,comseg; Bit32u pos; - PSP * callpsp=(PSP *)real_off(dos.psp,0); + PSP * callpsp=(PSP *)HostMake(dos.psp,0); if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false; if (flag!=OVERLAY) { @@ -252,9 +258,9 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) { DOS_SeekFile(fhandle,&pos,0); readsize=0xffff-256; if (flag==OVERLAY) { - DOS_ReadFile(fhandle,real_host(comseg,0),&readsize); + DOS_ReadFile(fhandle,HostMake(comseg,0),&readsize); } else { - DOS_ReadFile(fhandle,real_host(comseg,256),&readsize); + DOS_ReadFile(fhandle,HostMake(comseg,256),&readsize); } DOS_CloseFile(fhandle); if (flag==OVERLAY) /* Everything what should be done for Overlays */ @@ -262,19 +268,19 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) { SetupPSP(comseg,size,envseg); SetupCMDLine(comseg,block); /* Setup termination Address */ - RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip)); + 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=RealMake(Segs[ss].value,reg_sp); + 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: - SetSegment_16(cs,comseg); - SetSegment_16(ss,comseg); - SetSegment_16(ds,comseg); - SetSegment_16(es,comseg); + SegSet16(cs,comseg); + SegSet16(ss,comseg); + SegSet16(ds,comseg); + SegSet16(es,comseg); flags.intf=true; reg_ip=0x100; reg_sp=0xFFFE; @@ -291,7 +297,7 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) { } -static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) { +static bool EXE_Load(char * name,ParamBlock* _block,Bit8u flag) { EXE_Header header; Bit16u fhandle;Bit32u i; @@ -299,12 +305,17 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) { Bit16u envseg,pspseg,exeseg; Bit32u imagesize,headersize; - PSP * callpsp=(PSP *)real_off(dos.psp,0); + // 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; + envseg=block.exec.envseg; if (!MakeEnv(name,&envseg)) return false; }; @@ -339,15 +350,15 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) { return false; } SetupPSP(pspseg,size,envseg); - SetupCMDLine(pspseg,block); + SetupCMDLine(pspseg,&block); exeseg=pspseg+16; } else { /* For OVERLAY */ - exeseg=block->overlay.loadseg; + exeseg=block.overlay.loadseg; } /* Load the image in 32k blocks */ DOS_SeekFile(fhandle,&headersize,0); - Bit8u * imageoff=real_off(exeseg,0); + Bit8u * imageoff=HostMake(exeseg,0); //TODO File size checking and remove size // Remove psp size // imagesize=256; @@ -378,7 +389,7 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) { PhysPt address=Real2Phys(RealMake(RealSeg(reloc)+exeseg,RealOff(reloc))); Bit16u change=mem_readw(address); if (flag==OVERLAY) { - change+=block->overlay.relocation; + change+=block.overlay.relocation; } else { change+=exeseg; }; @@ -389,15 +400,15 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) { if (flag==OVERLAY) return true; /* Setup termination Address */ - RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip)); + RealSetVec(0x22,RealMakeSeg(cs,reg_ip)); /* Start up the actual EXE if we need to */ //TODO check for load and return - callpsp->stack=RealMake(Segs[ss].value,reg_sp); + callpsp->stack=RealMakeSeg(ss,reg_sp); dos.psp=pspseg; - SetSegment_16(cs,exeseg+header.initCS); - SetSegment_16(ss,exeseg+header.initSS); - SetSegment_16(ds,pspseg); - SetSegment_16(es,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; diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 34f3960..4ee82a0 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -18,11 +18,15 @@ #include #include +#include +#include + #include "dosbox.h" #include "mem.h" #include "cpu.h" #include "dos_inc.h" #include "drives.h" +#include "cross.h" #define DOS_FILESTART 4 @@ -37,7 +41,7 @@ Bit8u DOS_GetDefaultDrive(void) { } void DOS_SetDefaultDrive(Bit8u drive) { - CurrentDrive=drive; + if (drive<=DOS_DRIVES) CurrentDrive=drive; } bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { @@ -46,7 +50,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { Bit32u r=0;Bit32u w=0;Bit32u namestart=0; bool hasdrive=false; *drive=CurrentDrive; - char tempdir[DOS_NAMELENGTH]; + char tempdir[128]; //TODO Maybe check for illegal characters while (name[r]!=0 && (rDOS_DRIVES) || (!Drives[drive])) { DOS_SetError(DOSERR_INVALID_DRIVE); return false; } - strcpy((char *) buffer,Drives[drive]->curdir); + strcpy(buffer,Drives[drive]->curdir); return true; } @@ -265,7 +269,7 @@ bool DOS_CloseFile(Bit16u entry) { }; //TODO Figure this out with devices :) - PSP * psp=(PSP *)real_off(dos.psp,0); + PSP * psp=(PSP *)HostMake(dos.psp,0); Bit8u * table=Real2Host(psp->file_table); table[entry]=0xFF; /* Devices won't allow themselves to be closed or killed */ @@ -278,7 +282,7 @@ bool DOS_CloseFile(Bit16u entry) { bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { char fullname[DOS_PATHLENGTH];Bit8u drive; - PSP * psp=(PSP *)real_off(dos.psp,0); + PSP * psp=(PSP *)HostMake(dos.psp,0); if (!DOS_MakeName(name,fullname,&drive)) return false; /* Check for a free file handle */ Bit8u handle=DOS_FILES;Bit8u i; @@ -316,7 +320,7 @@ 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 *)real_off(dos.psp,0); + PSP * psp=(PSP *)HostMake(dos.psp,0); Bit8u handle=DOS_FindDevice((char *)name); bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; if (handle!=255) { @@ -377,7 +381,7 @@ bool DOS_GetFileAttr(char * name,Bit16u * attr) { } } -bool DOS_Canonicalize(char * name,Bit8u * big) { +bool DOS_Canonicalize(char * name,char * big) { //TODO Add Better support for devices and shit but will it be needed i doubt it :) Bit8u drive; char fullname[DOS_PATHLENGTH]; @@ -385,7 +389,7 @@ bool DOS_Canonicalize(char * name,Bit8u * big) { big[0]=drive+'A'; big[1]=':'; big[2]='\\'; - strcpy((char *)&big[3],fullname); + strcpy(&big[3],fullname); return true; }; @@ -409,7 +413,7 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; - PSP * psp=(PSP *)real_off(dos.psp,0); + PSP * psp=(PSP *)HostMake(dos.psp,0); Bit8u * table=Real2Host(psp->file_table); *newentry=0xff; for (Bit16u i=0;imax_files;i++) { @@ -426,6 +430,32 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { return true; }; +bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) { + Bit8u orig=RealHandle(entry); + if (orig>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[orig]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + Bit8u newone=RealHandle(newentry); + if (newone>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (Files[newone]) { + DOS_CloseFile(newentry); + return false; + }; + PSP * psp=(PSP *)HostMake(dos.psp,0); + Bit8u * table=Real2Host(psp->file_table); + table[newentry]=(Bit8u)entry; + return true; +}; + + bool DOS_CreateTempFile(char * name,Bit16u * entry) { @@ -446,9 +476,11 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) { } while (!DOS_CreateFile(name,0,entry)); return true; } -#if 0 -void FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){ + +#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'; @@ -457,115 +489,218 @@ void FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){ else{ naam[0]='\0'; }; - char temp[9]; + char temp[10]; fcb->Get_filename(temp); - temp[9]='.'; - strncat(naam,temp,9); - char ext[3]; + temp[8]='.'; + temp[9]='\0'; + strcat(naam,temp); + char ext[4]; fcb->Get_ext(ext); - if(drive!=0) { - strncat(&naam[11],ext,3); - naam[14]='\0'; - }else{ - strncat(&naam[9],ext,3); - naam[12]='\0'; - }; - DOS_MakeName(naam,outname, outdrive); - return; + ext[3]='\0'; + strcat(naam,ext); + return DOS_MakeName(naam,outname, outdrive); +} +#define FCB_SEP ":.;,=+" +#define ILLEGAL ":.;,=+ \t/\"[]<>|" + +static bool isvalid(const char* in){ + + const char ill[]=ILLEGAL; + return (Bit8u(*in)>0x1F) && (strchr(ill,*in)==0); } +static void vullen (char* veld,char* pveld){ + for(Bitu i=(pveld-veld);i'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 DOS_FCBOpen(Bit16u seg,Bit16u offset) { DOS_FCB fcb(seg,offset); Bit8u drive; char fullname[DOS_PATHLENGTH]; - FCB_MakeName (&fcb, fullname, &drive); - if(DOS_FileExists(fullname)==false) return false; - + if(!FCB_MakeName (&fcb, fullname, &drive)) return false; + if(!Drives[drive]->FileExists(fullname)) return false; //not really needed as stat will error. - struct stat stat_block; - stat(fullname, &stat_block); + struct stat stat_block; + if(!Drives[drive]->FileStat(fullname, &stat_block)) return false; fcb.Set_filesize((Bit32u)stat_block.st_size); - Bit16u constant =0; + Bit16u constant = 0; fcb.Set_current_block(constant); constant=0x80; fcb.Set_record_size(constant); + struct tm *time; - time=localtime(&stat_block.st_mtime); + 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); - fcb->Set_drive(drive +1); + 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 FCB_Close(void) -{ 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 FCB_FindFirst(Bit16u seg,Bit16u offset) -{FCB* fcb = new FCB(seg,offset); +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; + +} +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); - if(Drives[drive]->FindFirst(fullname,dtablock)==false) return false; - - char naam[8]; - char ext[3]; - char * point=strrchr(dtablock->name,'.'); - if(point==NULL|| *(point+1)=='\0') { - ext[0]=' '; - ext[1]=' '; - ext[2]=' '; - }else - {strcpy(ext,point+1); - Bitu i; - i=strlen(point+1); - while(i!=3) ext[i-1]=' '; - } + dtablock->sattr=DOS_ATTR_ARCHIVE; + dtablock->sdrive=drive; - if(point!=NULL) *point='\0'; - - strcpy (naam,dtablock->name); - i=strlen(dtablock->name); - while(i!=8) naam[i-1]=' '; - FCB* fcbout= new FCB((PhysPt)Real2Host(dos.dta)); - fcbout->Set_drive(drive +1); - fcbout->Set_filename(naam); - fcbout->Set_ext(ext); - return true; - } -bool FCB_FindNext(Bit16u seg,Bit16u offset) -{FCB* fcb = new FCB(seg,offset); - Bit8u drive; - Bitu i; - char fullname[DOS_PATHLENGTH]; - FCB_MakeName (fcb, fullname, &drive); - DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); if(Drives[dtablock->sdrive]->FindNext(dtablock)==false) return false; - char naam[8]; - char ext[3]; + 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); - Bitu i; - i=strlen(point+1); - while(i!=3) ext[i-1]=' '; + 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-1]=' '; - FCB* fcbout= new FCB((PhysPt)Real2Host(dos.dta)); + 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); @@ -575,12 +710,10 @@ bool FCB_FindNext(Bit16u seg,Bit16u offset) #endif bool DOS_FileExists(char * name) { - Bit16u handle; - if (DOS_OpenFile(name,0,&handle)) { - DOS_CloseFile(handle); - return true; - } - return false; + + char fullname[DOS_PATHLENGTH];Bit8u drive; + if (!DOS_MakeName(name,fullname,&drive)) return false; + return Drives[drive]->FileExists(fullname); } diff --git a/src/dos/dos_ioctl.cpp b/src/dos/dos_ioctl.cpp index 382b0bb..9b25352 100644 --- a/src/dos/dos_ioctl.cpp +++ b/src/dos/dos_ioctl.cpp @@ -44,6 +44,21 @@ 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; + } + return true; + } default: LOG_ERROR("DOS:IOCTL Call %2X Handle %2X unhandled",reg_al,handle); return false; diff --git a/src/dos/dos_memory.cpp b/src/dos/dos_memory.cpp index 5f1d90c..14e8a5d 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -29,15 +29,15 @@ static void DOS_CompressMemory(void) { MCB * pmcb;MCB * pmcbnext; Bit16u mcb_segment; mcb_segment=dos.firstMCB; - pmcb=(MCB *)real_off(mcb_segment,0); + pmcb=(MCB *)HostMake(mcb_segment,0); while (pmcb->type!=0x5a) { - pmcbnext=pmcbnext=(MCB *)real_off(mcb_segment+pmcb->size+1,0); + pmcbnext=pmcbnext=(MCB *)HostMake(mcb_segment+pmcb->size+1,0); if ((pmcb->psp_segment==0) && (pmcbnext->psp_segment==0)) { pmcb->size+=pmcbnext->size+1; pmcb->type=pmcbnext->type; } else { mcb_segment+=pmcb->size+1; - pmcb=(MCB *)real_off(mcb_segment,0); + pmcb=(MCB *)HostMake(mcb_segment,0); } } } @@ -45,14 +45,14 @@ static void DOS_CompressMemory(void) { void DOS_FreeProcessMemory(Bit16u pspseg) { MCB * pmcb; Bit16u mcb_segment=dos.firstMCB; - pmcb=(MCB *)real_off(mcb_segment,0); + pmcb=(MCB *)HostMake(mcb_segment,0); while (true) { if (pmcb->psp_segment==pspseg) { pmcb->psp_segment=MCB_FREE; } mcb_segment+=pmcb->size+1; if (pmcb->type==0x5a) break; - pmcb=(MCB *)real_off(mcb_segment,0); + pmcb=(MCB *)HostMake(mcb_segment,0); } DOS_CompressMemory(); }; @@ -64,7 +64,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { bool stop=false;mcb_segment=dos.firstMCB; DOS_CompressMemory(); while(!stop) { - pmcb=(MCB *)real_off(mcb_segment,0); + pmcb=(MCB *)HostMake(mcb_segment,0); if (pmcb->psp_segment==0) { /* Check for enough free memory in current block */ if (pmcb->size<(*blocks)) { @@ -78,7 +78,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { return true; } else { /* If so allocate it */ - pmcbnext=(MCB *)real_off(mcb_segment+*blocks+1,0); + pmcbnext=(MCB *)HostMake(mcb_segment+*blocks+1,0); pmcbnext->psp_segment=MCB_FREE; pmcbnext->type=pmcb->type; pmcbnext->size=pmcb->size-*blocks-1; @@ -105,8 +105,8 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { DOS_CompressMemory(); MCB * pmcb,* pmcbnext,* pmcbnew; - pmcb=(MCB *)real_off(segment-1,0); - pmcbnext=(MCB *)real_off(segment+pmcb->size,0); + pmcb=(MCB *)HostMake(segment-1,0); + pmcbnext=(MCB *)HostMake(segment+pmcb->size,0); Bit16u total=pmcb->size; if (pmcb->type!=0x5a) { if (pmcbnext->psp_segment==MCB_FREE) { @@ -118,7 +118,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { pmcb->type=pmcbnext->type; } pmcb->size=*blocks; - pmcbnew=(MCB *)real_off(segment+*blocks,0); + pmcbnew=(MCB *)HostMake(segment+*blocks,0); pmcbnew->size=total-*blocks-1; pmcbnew->type=pmcb->type; pmcbnew->psp_segment=MCB_FREE; @@ -141,7 +141,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { bool DOS_FreeMemory(Bit16u segment) { //TODO Check if allowed to free this segment MCB * pmcb; - pmcb=(MCB *)real_off(segment-1,0); + pmcb=(MCB *)HostMake(segment-1,0); pmcb->psp_segment=MCB_FREE; DOS_CompressMemory(); return true; @@ -153,10 +153,14 @@ 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 *) real_off(MEM_START,0); + 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)); } diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index f1e3c94..5a2857d 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -23,96 +23,101 @@ #include "support.h" #include "drives.h" #include "cross.h" - +#include "regs.h" +#include "callback.h" class MOUNT : public Program { public: - MOUNT(PROGRAM_Info * program_info); - void Run(void); -}; - - -MOUNT::MOUNT(PROGRAM_Info * info):Program(info) { - -} - - -void MOUNT::Run(void) { -/* Parse the command line */ - /* if the command line is empty show current mounts */ - - if (!*prog_info->cmd_line) { - WriteOut("Current mounted drives are\n"); - for (int d=0;dGetInfo()); + MOUNT(PROGRAM_Info * program_info):Program(program_info){}; + void Run(void){ + /* Parse the command line */ + /* if the command line is empty show current mounts */ + if (!*prog_info->cmd_line) { + WriteOut("Current mounted drives are\n"); + for (int d=0;dGetInfo()); + } } + return; } - return; - } - 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); - }; + char drive; drive=toupper(*prog_info->cmd_line); - 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; + 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 (Drives[drive-'A']) { + WriteOut("Drive %c already mounted with %s\n",drive,Drives[drive-'A']->GetInfo()); + 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); } - /* Not a switch so a normal directory/file */ - if (!(test.st_mode & S_IFDIR)) { - WriteOut("%s isn't a directory",dir); - return; - } - if (Drives[drive-'A']) { - WriteOut("Drive %c already mounted with %s\n",drive,Drives[drive-'A']->GetInfo()); - 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); -} +}; static void MOUNT_ProgramStart(PROGRAM_Info * info) { MOUNT * tempmount=new MOUNT(info); - tempmount->Run(); + tempmount->Run() ; delete tempmount; } - class MEM : public Program { public: - MEM(PROGRAM_Info * program_info); - void Run(void); + 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); + /* Test for and show free XMS */ + reg_ax=0x4300;CALLBACK_RunRealInt(0x2f); + if (reg_al==0x80) { + reg_ax=0x4310;CALLBACK_RunRealInt(0x2f); + Bit16u xms_seg=SegValue(es);Bit16u xms_off=reg_bx; + reg_ah=8; + CALLBACK_RunRealFar(xms_seg,xms_off); + if (!reg_bl) { + WriteOut("%10d Kb free extended memory\n",reg_dx); + } + } + /* Test for and show free EMS */ + Bit16u handle; + if (DOS_OpenFile("EMMXXXX0",0,&handle)) { + DOS_CloseFile(handle); + reg_ah=0x42; + CALLBACK_RunRealInt(0x67); + WriteOut("%10d Kb free expanded memory\n",reg_bx*16); + } + } }; -MEM::MEM(PROGRAM_Info * info):Program(info) { - -} - - -void MEM::Run(void) { - -} static void MEM_ProgramStart(PROGRAM_Info * info) { MEM mem(info); mem.Run(); - } @@ -203,7 +208,7 @@ static void UPCASE_ProgramStart(PROGRAM_Info * info) { void DOS_SetupPrograms(void) { PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart); -// PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); /*next release */ + PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); #if !defined (WIN32) /* Unix */ PROGRAMS_MakeFile("UPCASE.COM",UPCASE_ProgramStart); #endif diff --git a/src/dos/dos_tables.cpp b/src/dos/dos_tables.cpp index a2b2fce..2318655 100644 --- a/src/dos/dos_tables.cpp +++ b/src/dos/dos_tables.cpp @@ -20,13 +20,19 @@ #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 RealPt DOS_TableUpCase; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 9b7cf0a..1d78750 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -148,10 +148,14 @@ bool localDrive::FindNext(DTA_FindBlock * dta) { dta->attr=tempattr; dta->size=(Bit32u) stat_block.st_size; struct tm *time; - time=localtime(&stat_block.st_mtime); - - 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); + 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); + }else { + dta->time=6; + dta->date=4; + } return true; } @@ -178,15 +182,17 @@ bool localDrive::MakeDir(char * dir) { #if defined (WIN32) /* MS Visual C++ */ int temp=mkdir(newdir); #else - int temp=mkdir(newdir,0); + int temp=mkdir(newdir,0700); #endif - return (temp==0); + // if dir already exists, return success too. + return (temp==0) || ((temp!=0) && (errno==EEXIST)); } bool localDrive::RemoveDir(char * dir) { char newdir[512]; strcpy(newdir,basedir); strcat(newdir,dir); + CROSS_FILENAME(newdir); int temp=rmdir(newdir); return (temp==0); } @@ -195,6 +201,7 @@ bool localDrive::TestDir(char * dir) { char newdir[512]; strcpy(newdir,basedir); strcat(newdir,dir); + CROSS_FILENAME(newdir); int temp=access(newdir,F_OK); return (temp==0); } @@ -206,8 +213,8 @@ bool localDrive::Rename(char * oldname,char * newname) { CROSS_FILENAME(newold); char newnew[512]; strcpy(newnew,basedir); - strcat(newnew,newnew); - CROSS_FILENAME(newname); + strcat(newnew,newname); + CROSS_FILENAME(newnew); int temp=rename(newold,newnew); return (temp==0); @@ -223,6 +230,28 @@ bool localDrive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit return true; }; +bool localDrive::FileExists(const char* name) const { + char newname[512]; + strcpy(newname,basedir); + strcat(newname,name); + CROSS_FILENAME(newname); + FILE* Temp=fopen(newname,"rb"); + if(Temp==NULL) return false; + fclose(Temp); + return true; +} + +bool localDrive::FileStat(const char* name, struct stat* const stat_block) const { + char newname[512]; + strcpy(newname,basedir); + strcat(newname,name); + CROSS_FILENAME(newname); + if(stat(newname,stat_block)!=0) return false; + return true; + +} + + localDrive::localDrive(char * startdir) { strcpy(basedir,startdir); @@ -237,10 +266,15 @@ bool localFile::Read(Bit8u * data,Bit16u * size) { }; bool localFile::Write(Bit8u * data,Bit16u * size) { - *size=fwrite(data,1,*size,fhandle); + if(*size==0){ + return (!ftruncate(fileno(fhandle),ftell(fhandle))); + } + else + { + *size=fwrite(data,1,*size,fhandle); return true; + } } - bool localFile::Seek(Bit32u * pos,Bit32u type) { int seektype; switch (type) { @@ -275,3 +309,4 @@ localFile::localFile(FILE * handle,Bit16u devinfo) { info=devinfo; } + diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index b8140e1..0be5dc6 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.cpp @@ -19,10 +19,12 @@ #include #include #include +#include #include "dosbox.h" #include "dos_system.h" #include "drives.h" #include "support.h" +#include "cross.h" struct VFILE_Block { char * name; @@ -151,6 +153,32 @@ 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; + 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.....)*/ + return true; + } + cur_file=cur_file->next; + } + return false; +} + +bool Virtual_Drive::FileExists(const char* name) const { + VFILE_Block * cur_file=first_file; + while (cur_file) { + if (strcasecmp(name,cur_file->name)==0) return true; + cur_file=cur_file->next; + } + return false; +} + static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) { strcpy(dta->name,fill_file->name); dta->size=fill_file->size; diff --git a/src/dos/drives.h b/src/dos/drives.h index a2dcf75..b46e376 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -21,7 +21,7 @@ #include #include - +#include "dos_system.h" class localDrive : public DOS_Drive { public: @@ -37,6 +37,8 @@ public: 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; private: bool FillDTABlock(DTA_FindBlock * dta); char basedir[512]; @@ -63,6 +65,9 @@ public: 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; + private: VFILE_Block * search_file; char search_string[255]; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 4fdfe00..e5ea0c7 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "dosbox.h" #include "debug.h" #include "cpu.h" @@ -104,7 +105,7 @@ void DOS_Init(); void RENDER_Init(void); void CPU_Init(); -void FPU_Init(); +//void FPU_Init(); void IO_Init(void); void DMA_Init(void); void MIXER_Init(void); @@ -188,6 +189,9 @@ void DOSBOX_SetLoop(LoopHandler * handler) { loop=handler; } +void DOSBOX_SetNormalLoop() { + loop=Normal_Loop; +} void DOSBOX_RunMachine(void){ Bitu ret; @@ -207,9 +211,11 @@ static void InitSystems(void) { HARDWARE_Init(); TIMER_Init(); CPU_Init(); +#if C_FPU FPU_Init(); +#endif MIXER_Init(); -#ifdef C_DEBUG +#if C_DEBUG DEBUG_Init(); #endif //Start up individual hardware @@ -241,10 +247,19 @@ static void InitSystems(void) { void DOSBOX_Init(int argc, char* argv[]) { /* Find the base directory */ - strcpy(dosbox_basedir,argv[0]); + 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) E_Exit("Can't find basedir"); + 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) { @@ -291,7 +306,5 @@ void DOSBOX_Init(int argc, char* argv[]) { void DOSBOX_StartUp(void) { - SHELL_AddAutoexec("SET PATH=Z:\\"); - SHELL_AddAutoexec("SET COMSPEC=Z:\\COMMAND.COM"); SHELL_Init(); }; diff --git a/src/dosbox.lang b/src/dosbox.lang index 2a68c7f..783083c 100644 --- a/src/dosbox.lang +++ b/src/dosbox.lang @@ -71,5 +71,5 @@ The DOSBox Team Drive %c does not exist! . :SHELL_EXECUTE_ILLEGAL_COMMAND -Illegal command +Illegal command: %s . diff --git a/src/fpu/Makefile.am b/src/fpu/Makefile.am index d1890ca..fb3045f 100644 --- a/src/fpu/Makefile.am +++ b/src/fpu/Makefile.am @@ -1,4 +1,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libfpu.a -libfpu_a_SOURCES = fpu.cpp fpu_load.h \ No newline at end of file +libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h \ No newline at end of file diff --git a/src/fpu/Makefile.in b/src/fpu/Makefile.in index c4738cd..370c64f 100644 --- a/src/fpu/Makefile.in +++ b/src/fpu/Makefile.in @@ -84,7 +84,7 @@ install_sh = @install_sh@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libfpu.a -libfpu_a_SOURCES = fpu.cpp fpu_load.h +libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h subdir = src/fpu mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h @@ -93,7 +93,7 @@ LIBRARIES = $(noinst_LIBRARIES) libfpu_a_AR = $(AR) cru libfpu_a_LIBADD = -am_libfpu_a_OBJECTS = fpu.$(OBJEXT) +am_libfpu_a_OBJECTS = fpu.$(OBJEXT) fpu_flags.$(OBJEXT) libfpu_a_OBJECTS = $(am_libfpu_a_OBJECTS) DEFS = @DEFS@ @@ -103,7 +103,7 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fpu.Po +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fpu.Po ./$(DEPDIR)/fpu_flags.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -145,6 +145,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu_flags.Po@am__quote@ distclean-depend: -rm -rf ./$(DEPDIR) diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index ad4fa92..79ee2b9 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -16,12 +16,15 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "dosbox.h" +#if C_FPU + #include #include #include "mem.h" -#include "dosbox.h" +#include "fpu.h" -typedef PhysOff EAPoint; +typedef PhysPt EAPoint; #define LoadMb(off) mem_readb(off) #define LoadMw(off) mem_readw(off) @@ -35,28 +38,240 @@ typedef PhysOff EAPoint; #define SaveMw(off,val) mem_writew(off,val) #define SaveMd(off,val) mem_writed(off,val) -typedef long double FPUREG; +typedef double Real; +#include "fpu_types.h" +#include "fpu_instructions.h" -#include "fpu_load.h" +FPU_Flag_Info fpu_flags; +FPU_Reg fpu_regs[8]; +#define FPU_GetZF fpu_flags.sw.zf = FPU_get_ZF(); +#define FPU_ParseCW(newcw) { \ + fpu_flags.cw.ic = ((bool)((newcw&0x1000)>>12)?true:false); \ + fpu_flags.cw.rc = (Bit8u)((newcw&0x0C00)>>10); \ + fpu_flags.cw.pc = (Bit8u)((newcw&0x0300)>>8); \ + fpu_flags.cw.ie = ((bool)((newcw&0x0080)>>7)?true:false); \ + fpu_flags.cw.sf = ((bool)((newcw&0x0040)>>6)?true:false); \ + fpu_flags.cw.pf = ((bool)((newcw&0x0020)>>5)?true:false); \ + fpu_flags.cw.uf = ((bool)((newcw&0x0010)>>4)?true:false); \ + fpu_flags.cw.of = ((bool)((newcw&0x0008)>>3)?true:false); \ + fpu_flags.cw.zf = ((bool)((newcw&0x0004)>>2)?true:false); \ + fpu_flags.cw.df = ((bool)((newcw&0x0002)>>1)?true:false); \ + fpu_flags.cw.in = ((bool)(newcw&0x0001)?true:false); \ +} +#define FPU_makeCW(newcw) { \ + newcw = (Bit16u)fpu_flags.cw.in; \ + newcw |= (fpu_flags.cw.df<<1); \ + newcw |= (fpu_flags.cw.zf<<2); \ + newcw |= (fpu_flags.cw.of<<3); \ + newcw |= (fpu_flags.cw.uf<<4); \ + newcw |= (fpu_flags.cw.pf<<5); \ + newcw |= (fpu_flags.cw.sf<<6); \ + newcw |= (fpu_flags.cw.ie<<7); \ + newcw |= (fpu_flags.cw.pc<<8); \ + newcw |= (fpu_flags.cw.rc<<10); \ + newcw |= (fpu_flags.cw.ic<<12); \ +} +#define FPU_ParseSW(newsw) { \ + fpu_flags.sw.bf = ((bool)((newsw&0x8000)>>15)?true:false); \ + fpu_flags.sw.c3 = ((bool)((newsw&0x4000)>>14)?true:false); \ + fpu_flags.sw.tos = (Bit8s)((newsw&0x3800)>>11); \ + fpu_flags.sw.c2 = ((bool)((newsw&0x0400)>>10)?true:false); \ + fpu_flags.sw.c1 = ((bool)((newsw&0x0200)>>9)?true:false); \ + fpu_flags.sw.c0 = ((bool)((newsw&0x0100)>>8)?true:false); \ + fpu_flags.sw.ir = ((bool)((newsw&0x0080)>>7)?true:false); \ + fpu_flags.sw.sf = ((bool)((newsw&0x0040)>>6)?true:false); \ + fpu_flags.sw.pf = ((bool)((newsw&0x0020)>>5)?true:false); \ + fpu_flags.sw.uf = ((bool)((newsw&0x0010)>>4)?true:false); \ + fpu_flags.sw.of = ((bool)((newsw&0x0008)>>3)?true:false); \ + fpu_flags.sw.zf = ((bool)((newsw&0x0004)>>2)?true:false); \ + fpu_flags.sw.df = ((bool)((newsw&0x0002)>>1)?true:false); \ + fpu_flags.sw.in = ((bool)(newsw&0x0001)?true:false); \ +} -void FPU_ESC0_EA(Bitu rm,PhysOff addr) { +#define FPU_makeSW(newsw) { \ + newsw = (Bit16u)fpu_flags.sw.in; \ + newsw |= (fpu_flags.sw.df<<1); \ + newsw |= (fpu_flags.sw.zf<<2); \ + newsw |= (fpu_flags.sw.of<<3); \ + newsw |= (fpu_flags.sw.uf<<4); \ + newsw |= (fpu_flags.sw.pf<<5); \ + newsw |= (fpu_flags.sw.sf<<6); \ + newsw |= (fpu_flags.sw.ir<<7); \ + newsw |= (fpu_flags.sw.c0<<8); \ + newsw |= (fpu_flags.sw.c1<<9); \ + newsw |= (fpu_flags.sw.c2<<10); \ + newsw |= (fpu_flags.sw.tos<<11); \ + newsw |= (fpu_flags.sw.c3<<14); \ + newsw |= (fpu_flags.sw.bf<<15); \ +} +#define FPU_LOADFLAGS { \ + fpu_flags.sw.bf = false; \ + fpu_flags.sw.c3 = FPU_get_C3(); \ + fpu_flags.sw.c2 = FPU_get_C2(); \ + fpu_flags.sw.c1 = FPU_get_C1(); \ + fpu_flags.sw.c0 = FPU_get_C0(); \ + fpu_flags.sw.ir = FPU_get_IR(); \ + fpu_flags.sw.sf = FPU_get_SF(); \ + fpu_flags.sw.pf = FPU_get_PF(); \ + fpu_flags.sw.uf = FPU_get_UF(); \ + fpu_flags.sw.of = FPU_get_OF(); \ + fpu_flags.sw.zf = FPU_get_ZF(); \ + fpu_flags.sw.df = FPU_get_DF(); \ + fpu_flags.sw.in = FPU_get_IN(); \ +} +void FPU_ESC0_EA(Bitu rm,PhysPt addr) { } void FPU_ESC0_Normal(Bitu rm) { - - } +void FPU_ESC1_EA(Bitu rm,PhysPt addr) { + Bit16u cw; + Bitu opcode = (rm&0x38)>>3; + + switch(opcode) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 6: + break; + case 5: + FPU_ParseCW(LoadMw(addr)); /* FLDCW */ + break; + case 7: /* FSTCW */ + FPU_makeCW(cw); + SaveMw(addr,cw); + break; + } +} + +void FPU_ESC1_Normal(Bitu rm) { + Bitu opcode = (rm&0xF0); + + switch(opcode) { + case 0xC0: +// if(rm&8) +// else + FLDST(rm-0xC0); /* FLDST */ + break; + case 0xD0: + break; + } + switch(rm) { + case 0xE0: /* FCHS */ + FCHS; + break; + case 0xE8: /* FLD1 */ + FLD(1); + break; + case 0xEE: /* FLDZ */ + FLD(0); + break; + } +} + + +void FPU_ESC2_EA(Bitu rm,PhysPt addr) { +} + +void FPU_ESC2_Normal(Bitu rm) { +} + + +void FPU_ESC3_EA(Bitu rm,PhysPt addr) { +} + +void FPU_ESC3_Normal(Bitu rm) { + switch( rm ) { + case 0xE3: /* FINIT */ + FPU_ParseCW(0x037F); + for(int i=0;i<8;i++) { + fpu_regs.st[i].r = 0; + fpu_regs.st[i].tag = FPUREG_EMPTY; + } + break; + } +} + + +void FPU_ESC4_EA(Bitu rm,PhysPt addr) { +} + +void FPU_ESC4_Normal(Bitu rm) { +} + + +void FPU_ESC5_EA(Bitu rm,PhysPt addr) { + Bit16u sw; + Bitu opcode = (rm&0x38)>>3; + + switch(opcode) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: /* FSTSW */ + FPU_LOADFLAGS; + FPU_makeSW(sw); + SaveMw(addr,sw); + break; + } +} + +void FPU_ESC5_Normal(Bitu rm) { +} + + +void FPU_ESC6_EA(Bitu rm,PhysPt addr) { +} + +void FPU_ESC6_Normal(Bitu rm) { + Bitu opcode = (rm&0xF0); + + if(rm==0xD9) { /* FCOMPP */ + FCOMPP; + return; + } + switch(opcode) { + case 0xC0: +// if(rm&8) + break; + case 0xD0: +// if(rm&8) + break; + case 0xE0: +// if(rm&8) + break; + case 0xF0: + if(rm&8) + FDIVP(rm-0xF8,0); + break; + } +} + + +void FPU_ESC7_EA(Bitu rm,PhysPt addr) { +} + +void FPU_ESC7_Normal(Bitu rm) { +} void FPU_Init(void) { + fpu_flags.type = t_FUNKNOWN; +} -} \ No newline at end of file +#endif diff --git a/src/fpu/fpu_flags.cpp b/src/fpu/fpu_flags.cpp new file mode 100644 index 0000000..924614f --- /dev/null +++ b/src/fpu/fpu_flags.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "fpu.h" +#include "pic.h" +#include "fpu_types.h" +extern FPU_Flag_Info fpu_flags; + +bool FPU_get_C3() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c3; + case t_FCOMP: + return (fpu_flags.result.tag==FPUREG_EMPTY||fpu_flags.result.tag==FPUREG_ZERO); + default: + E_Exit("FPU_get_C3 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_C2() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c2; + case t_FCOMP: + return (fpu_flags.result.tag==FPUREG_EMPTY); + default: + E_Exit("FPU_get_C2 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_C1() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c1; + case t_FCOMP: + return false; /* FIXME */ + default: + E_Exit("FPU_get_C1 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_C0() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.c0; + case t_FCOMP: + return (fpu_flags.result.tag!=FPUREG_ZERO&&fpu_flags.result.tag!=FPUREG_PNAN); + default: + E_Exit("FPU_get_C0 Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_IR() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.ir; + default: + E_Exit("FPU_get_IR Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_SF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.sf; + case t_FCOMP: + return false; /* FIXME */ + default: + E_Exit("FPU_get_SF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_PF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.pf; + default: + E_Exit("FPU_get_PF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_UF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.uf; + default: + E_Exit("FPU_get_UF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_OF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.of; + default: + E_Exit("FPU_get_OF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_ZF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + case t_FCOMP: + return fpu_flags.sw.zf; + case t_FDIV: + case t_FDIVP: + return (fpu_flags.result.tag==FPUREG_PNAN||fpu_flags.result.tag==FPUREG_NNAN); + default: + E_Exit("FPU_get_ZF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_DF() { + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.df; + case t_FCOMP: + return false; /* FIXME */ + default: + E_Exit("FPU_get_DF Unknown %d",fpu_flags.type); + } + return 0; +} + +bool FPU_get_IN(){ + switch(fpu_flags.type) { + case t_FLD: + case t_FLDST: + case t_FDIV: + case t_FDIVP: + case t_FCHS: + case t_FUNKNOWN: + case t_FNOTDONE: + return fpu_flags.sw.in; + case t_FCOMP: + return (fpu_flags.result.tag==FPUREG_EMPTY); /* FIXME */ + default: + E_Exit("FPU_get_IN Unknown %d",fpu_flags.type); + } + return 0; +} diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h new file mode 100644 index 0000000..49de9d0 --- /dev/null +++ b/src/fpu/fpu_instructions.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define FLD(op1) { \ + FPU_GetZF; \ + fpu_flags.type=t_FLD; \ + if(--fpu_flags.sw.tos < 0) \ + fpu_flags.sw.tos = 7; \ + if( fpu_regs.st[fpu_flags.sw.tos].tag != FPUREG_EMPTY ) { \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ + break; \ + } \ + if(op1) \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_VALID; \ + else \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_ZERO; \ + fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = op1; \ +} + +#define FLDST(op1) { \ + FPU_GetZF; \ + fpu_flags.type=t_FLDST; \ + Bit8u reg = fpu_flags.sw.tos+op1; \ + if(reg>7) reg-=8; \ + if(--fpu_flags.sw.tos < 0) \ + fpu_flags.sw.tos = 7; \ + if(fpu_regs.st[fpu_flags.sw.tos].tag!=FPUREG_EMPTY) { \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ + break; \ + } \ + fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = fpu_regs.st[reg].tag; \ + fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = fpu_regs.st[reg].r; \ +} + +#define FPOP { \ + fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_EMPTY; \ + if(++fpu_flags.sw.tos > 7 ) \ + fpu_flags.sw.tos = 0; \ +} +/* FPOP: fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = 0; is not really neccessary */ + +#define FDIVP(op1,op2) { \ + Bit8u reg1 = fpu_flags.sw.tos+op1; \ + Bit8u reg2 = fpu_flags.sw.tos+op2; \ + fpu_flags.type=t_FDIVP; \ + if(reg1>7) reg1-=8; \ + if(reg2>7) reg2-=8; \ + if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + FPOP; \ + break; \ + } \ + if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \ + if(fpu_regs.st[reg1].r > 0) \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \ + else \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + FPOP; \ + break; \ + } \ + if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \ + FPOP; \ + break; \ + } \ + fpu_flags.result.tag = FPUREG_VALID; \ + fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \ + FPOP; \ +} + +#define FDIV(op1,op2) { \ + Bit8u reg1 = fpu_flags.sw.tos+op1; \ + Bit8u reg2 = fpu_flags.sw.tos+op2; \ + fpu_flags.type=t_FDIV; \ + if(reg1>7) reg1-=7; \ + if(reg2>7) reg2-=7; \ + if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + break; \ + } \ + if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \ + if(fpu_regs.st[reg1].r > 0) \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \ + else \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ + break; \ + } \ + if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \ + fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \ + break; \ + } \ + fpu_flags.result.tag = FPUREG_VALID; \ + fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \ +} + +#define FCHS { \ + FPU_GetZF; \ + fpu_flags.type=t_FCHS; \ + if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_PNAN) { \ + fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ + } else if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_NNAN) { \ + fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_PNAN; \ + } else \ + fpu_regs.st[fpu_flags.sw.tos].r = -fpu_regs.st[fpu_flags.sw.tos].r; \ +} + +#define FCOMPP { \ + Bit8u reg = fpu_flags.sw.tos+1; \ + FPU_GetZF; \ + fpu_flags.type=t_FCOMP; \ + if(reg>7) \ + reg=0; \ + if((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)&&(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO)) { \ + fpu_flags.result.r = fpu_regs.st[reg].r - fpu_regs.st[fpu_flags.sw.tos].r; \ + if(fpu_flags.result.r==0) \ + fpu_flags.result.tag = FPUREG_ZERO; \ + else \ + fpu_flags.result.tag = FPUREG_VALID; \ + FPOP; \ + FPOP; \ + return; \ + } else if(((fpu_regs.st[reg].tag==FPUREG_EMPTY)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_EMPTY))||((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO))) { \ + fpu_flags.result.tag = FPUREG_EMPTY; \ + FPOP; \ + FPOP; \ + return; \ + } \ + Bit8s res = (fpu_regs.st[reg].tag-fpu_regs.st[fpu_flags.sw.tos].tag); \ + if(res==0||fpu_flags.cw.ic==0) { \ + fpu_flags.result.tag = FPUREG_ZERO; \ + FPOP; \ + FPOP; \ + return; \ + } else if(res>0) { \ + fpu_flags.result.tag = FPUREG_NNAN; \ + FPOP; \ + FPOP; \ + return; \ + } \ + fpu_flags.result.tag = FPUREG_PNAN; \ + FPOP; \ + FPOP; \ +} + + + + diff --git a/src/fpu/fpu_load.h b/src/fpu/fpu_load.h deleted file mode 100644 index b7f6ee0..0000000 --- a/src/fpu/fpu_load.h +++ /dev/null @@ -1,21 +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. - */ - -INLINE FPUREG Load_Short(EAPoint addr) { - return (Bit16s)mem_readw(addr); -} \ No newline at end of file diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h new file mode 100644 index 0000000..2d0ced0 --- /dev/null +++ b/src/fpu/fpu_types.h @@ -0,0 +1,33 @@ + + +enum { FPUREG_VALID=0, FPUREG_ZERO, FPUREG_PNAN, FPUREG_NNAN, FPUREG_EMPTY }; + +enum { + t_FLD=0, t_FLDST, t_FDIV, + t_FDIVP, t_FCHS, t_FCOMP, + + t_FUNKNOWN, + t_FNOTDONE +}; + +struct FPU_Flag_Info { + struct { + Real64 r; + Bit8u tag; + } var1,var2, result; + struct { + bool bf,c3,c2,c1,c0,ir,sf,pf,uf,of,zf,df,in; + Bit8s tos; + } sw; + struct { + bool ic,ie,sf,pf,uf,of,zf,df,in; + Bit8u rc,pc; + } cw; + Bitu type; + Bitu prev_type; +}; + +struct FPU_Reg { + Real64 r; + Bit8u tag; +}; diff --git a/src/gui/render.cpp b/src/gui/render.cpp index b6867b0..04c3b47 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -67,13 +67,13 @@ static void MakeTables(void) { Bitu i;Bit32u c,a; c=0;a=(render.src.width<<16)/gfx_info.width; for (i=0;i> 16; c=(c&0xffff)+a; + render.stretch_x[i]=c>> 16; } c=0;a=(render.src.height<<16)/gfx_info.height; for (i=0;i> 16)*render.src.pitch; c=(c&0xffff)+a; + render.stretch_y[i]=(c>>16)*render.src.pitch; } } diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 08e40d3..63810e9 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -122,7 +122,7 @@ static void SwitchFullScreen(void) { } static void GFX_Redraw() { -#ifdef C_THREADED +#if C_THREADED if (SDL_mutexP(sdl.mutex)) { E_Exit("Can't Lock Mutex"); }; @@ -134,7 +134,7 @@ static void GFX_Redraw() { if (sdl.full_screen) SDL_Flip(sdl.surface); else SDL_UpdateRect(sdl.surface,0,0,0,0); }; -#ifdef C_THREADED +#if C_THREADED if (SDL_mutexV(sdl.mutex)) { E_Exit("Can't Release Mutex"); } @@ -151,7 +151,7 @@ static int SDLGFX_Thread(void * data) { void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { /* I should probably not change the GFX_PalEntry :) */ -#ifdef C_THREADED +#if C_THREADED if (SDL_mutexP(sdl.mutex)) { E_Exit("SDL:Can't Lock Mutex"); }; @@ -166,7 +166,7 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { } } /* Copy palette entries into some internal back up table */ -#ifdef C_THREADED +#if C_THREADED if (SDL_mutexV(sdl.mutex)) { E_Exit("SDL:Can't Release Mutex"); } @@ -179,11 +179,11 @@ void GFX_SetDrawHandler(GFX_DrawHandler * handler) { } void GFX_Stop() { -#ifdef C_THREADED +#if C_THREADED SDL_mutexP(sdl.mutex); #endif sdl.active=false; -#ifdef C_THREADED +#if C_THREADED SDL_mutexV(sdl.mutex); #endif } @@ -198,7 +198,7 @@ void GFX_StartUp() { sdl.active=false; sdl.full_screen=false; sdl.draw=0; -#ifdef C_THREADED +#if C_THREADED sdl.mutex=SDL_CreateMutex(); sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0); #else @@ -485,7 +485,7 @@ int main(int argc, char* argv[]) { #endif ) < 0 ) { - E_Exit("Can't init SDL"); + E_Exit("Can't init SDL %s",SDL_GetError()); } GFX_StartUp(); /* Init all the dosbox subsystems */ @@ -497,9 +497,9 @@ int main(int argc, char* argv[]) { 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 } -/* Start dosbox up */ +#endif + /* Start dosbox up */ DOSBOX_StartUp(); } catch (Bitu e) { diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index 62e9a6c..2a50e17 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.cpp @@ -33,7 +33,7 @@ #include "inout.h" #include "dma.h" -#ifdef DEBUG_DMA +#if DEBUG_DMA #define DMA_DEBUG LOG_DEBUG #else #define DMA_DEBUG @@ -57,7 +57,7 @@ struct DMA_CHANNEL { Bit32u current_count; Bit8u page; bool masked; - HostOff host_address; + PhysPt address; bool addr_changed; }; @@ -142,73 +142,62 @@ void write_dma_page(Bit32u port,Bit8u val) { } } -void DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { +Bit16u DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { DMA_CHANNEL * chan=&dma[0].chan[dmachan]; + if (chan->masked) return 0; + if (!count) return 0; /* DMA always does autoinit should work under normal situations */ if (chan->addr_changed) { /* Calculate the new starting position for dma read*/ chan->addr_changed=false; - chan->host_address=memory+(chan->page << 16)+chan->base_address; + chan->address=(chan->page << 16)+chan->base_address; chan->current_count=chan->base_count+1; chan->current_address=chan->base_address; DMA_DEBUG("DMA:Transfer from %d size %d",(chan->page << 16)+chan->base_address,chan->current_count); } - if (!count) return; if (chan->current_count>=count) { - memcpy(buffer,chan->host_address,count); - chan->host_address+=count; + MEM_BlockRead(chan->address,buffer,count); + chan->address+=count; chan->current_address+=count; chan->current_count-=count; - return; + return count; } else { /* Copy remaining piece of first buffer */ - memcpy(buffer,chan->host_address,chan->current_count); + MEM_BlockRead(chan->address,buffer,chan->current_count); buffer+=chan->current_count; count-=(Bit16u)chan->current_count; /* Autoinit reset the dma channel */ - chan->host_address=memory+(chan->page << 16)+chan->base_address; + chan->address=(chan->page << 16)+chan->base_address; chan->current_count=chan->base_count+1; chan->current_address=chan->base_address; /* Copy the rest of the buffer */ - memcpy(buffer,chan->host_address,count); - chan->host_address+=count; + MEM_BlockRead(chan->address,buffer,count); + chan->address+=count; chan->current_address+=count; chan->current_count-=count; - return; + return count; } }; -void DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { - if (dma[0].chan[dmachan].addr_changed) { - /* Calculate the new starting position for dma read*/ - dma[0].chan[dmachan].addr_changed=false; - dma[0].chan[dmachan].host_address=memory+(dma[0].chan[dmachan].page << 16)+dma[0].chan[dmachan].base_address; - dma[0].chan[dmachan].current_count=dma[0].chan[dmachan].base_count; - dma[0].chan[dmachan].current_count=dma[0].chan[dmachan].current_count; - } - if (dma[0].chan[dmachan].current_count>=count) { - memcpy(dma[0].chan[dmachan].host_address,buffer,count); - dma[0].chan[dmachan].host_address+=count; - dma[0].chan[dmachan].current_address+=count; - dma[0].chan[dmachan].current_count-=count; - return; - } else { +Bit16u DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { - } - return; + return 0; }; -void DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { +Bit16u DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + return 0; } -void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { +Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + + return 0; } diff --git a/src/hardware/hardware.cpp b/src/hardware/hardware.cpp index 79ccf08..ed73820 100644 --- a/src/hardware/hardware.cpp +++ b/src/hardware/hardware.cpp @@ -1,117 +1,117 @@ -/* - * 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. - */ - -/* - This could do with a serious revision :) -*/ - -#include -#include "dosbox.h" -#include "programs.h" -#include "hardware.h" - -static HWBlock * firsthw=0; - - -class HWSET : public Program { -public: - HWSET(PROGRAM_Info * program_info); - void Run(void); - -}; - - -HWSET::HWSET(PROGRAM_Info * info):Program(info) { - -} - -void HW_Register(HWBlock * block) { - block->next=firsthw; - firsthw=block; -} - - -void HWSET::Run(void) { - /* Hopefull enough space */ - char buf[1024]; - - HWBlock * loopblock; - if (!*prog_info->cmd_line) { - /* No command line given give overview of hardware */ - loopblock=firsthw; - WriteOut("ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"); - WriteOut("³Device ³Full Name ³Status ³"); - WriteOut("ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´"); - while (loopblock) { - if (loopblock->show_status) { - loopblock->show_status(buf); - } else { - strcpy(buf,"No Status Handler"); - } - WriteOut("³%-8s³%-25s³%-43s³",loopblock->dev_name,loopblock->full_name,buf); - loopblock=loopblock->next; - } - WriteOut("ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"); - WriteOut("If you want to setup specific hardware use \"HWSET Device\" for information.\n"); - return; - } - /* Command line given */ - if (strcmp(prog_info->cmd_line,"/?")==0) { - WriteOut("Hardware setup tool for DOSBox.\n"); - WriteOut("This program can be used to change the settings of internal hardware.\n\n" - "HWSET [device] [switches]\n\n" - "Using an empty command line gives you a list of hardware.\n" - "You can get list of switches for a device with HWSET device.\n" - ); - return; - } - char * rest=strchr(prog_info->cmd_line,' '); - if (rest) *rest++=0; - loopblock=firsthw; - while (loopblock) { - if (strcasecmp(loopblock->dev_name,prog_info->cmd_line)==0) goto founddev; - loopblock=loopblock->next; - } - WriteOut("Device %s not found\n",prog_info->cmd_line); - return; -founddev: -/* Check for rest of line */ - if (rest) { - strcpy(buf,rest); - loopblock->get_input(buf); - WriteOut(buf); - - } else { - WriteOut("Command overview for %s\n%s",loopblock->full_name,loopblock->help); - } - return; -} - -static void HWSET_ProgramStart(PROGRAM_Info * info) { - HWSET * tempHWSET=new HWSET(info); - tempHWSET->Run(); - delete tempHWSET; -} - - - -void HARDWARE_Init(void) { - PROGRAMS_MakeFile("HWSET.COM",HWSET_ProgramStart); - -}; - +/* + * 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. + */ + +/* + This could do with a serious revision :) +*/ + +#include +#include "dosbox.h" +#include "programs.h" +#include "hardware.h" + +static HWBlock * firsthw=0; + + +class HWSET : public Program { +public: + HWSET(PROGRAM_Info * program_info); + void Run(void); + +}; + + +HWSET::HWSET(PROGRAM_Info * info):Program(info) { + +} + +void HW_Register(HWBlock * block) { + block->next=firsthw; + firsthw=block; +} + + +void HWSET::Run(void) { + /* Hopefull enough space */ + char buf[1024]; + + HWBlock * loopblock; + if (!*prog_info->cmd_line) { + /* No command line given give overview of hardware */ + loopblock=firsthw; + WriteOut("ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"); + WriteOut("³Device ³Full Name ³Status ³"); + WriteOut("ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´"); + while (loopblock) { + if (loopblock->show_status) { + loopblock->show_status(buf); + } else { + strcpy(buf,"No Status Handler"); + } + WriteOut("³%-8s³%-25s³%-43s³",loopblock->dev_name,loopblock->full_name,buf); + loopblock=loopblock->next; + } + WriteOut("ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"); + WriteOut("If you want to setup specific hardware use \"HWSET Device\" for information.\n"); + return; + } + /* Command line given */ + if (strcmp(prog_info->cmd_line,"/?")==0) { + WriteOut("Hardware setup tool for DOSBox.\n"); + WriteOut("This program can be used to change the settings of internal hardware.\n\n" + "HWSET [device] [switches]\n\n" + "Using an empty command line gives you a list of hardware.\n" + "You can get list of switches for a device with HWSET device.\n" + ); + return; + } + char * rest=strchr(prog_info->cmd_line,' '); + if (rest) *rest++=0; + loopblock=firsthw; + while (loopblock) { + if (strcasecmp(loopblock->dev_name,prog_info->cmd_line)==0) goto founddev; + loopblock=loopblock->next; + } + WriteOut("Device %s not found\n",prog_info->cmd_line); + return; +founddev: +/* Check for rest of line */ + if (rest) { + strcpy(buf,rest); + loopblock->get_input(buf); + WriteOut(buf); + + } else { + WriteOut("Command overview for %s\n%s",loopblock->full_name,loopblock->help); + } + return; +} + +static void HWSET_ProgramStart(PROGRAM_Info * info) { + HWSET * tempHWSET=new HWSET(info); + tempHWSET->Run(); + delete tempHWSET; +} + + + +void HARDWARE_Init(void) { + PROGRAMS_MakeFile("HWSET.COM",HWSET_ProgramStart); + +}; + diff --git a/src/hardware/keyboard.cpp b/src/hardware/keyboard.cpp index f29cc65..cc9c85b 100644 --- a/src/hardware/keyboard.cpp +++ b/src/hardware/keyboard.cpp @@ -63,10 +63,12 @@ static Bit8u read_p61(Bit32u port) { static void write_p61(Bit32u port,Bit8u val) { //TODO Enable spreaker through here :) if ((val&128)) { /* Keyboard acknowledge */ - kbuf_used--; - kbuf_pos++; - if (kbuf_pos>=KEYBUFSIZE) kbuf_pos=0; - if (kbuf_used>0) PIC_ActivateIRQ(1); + 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 & 3)==3) { diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index d2fd529..2616494 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -15,38 +15,25 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + #include #include #include #include "dosbox.h" #include "mem.h" -#define MEM_MAXSIZE 16 /* The Size of memory used to get size of page table */ -#define memsize 8 /* 8 mb of memory */ -#define EMM_HANDLECOUNT 250 +HostPt memory; +HostPt ReadHostTable[MAX_PAGES]; +HostPt WriteHostTable[MAX_PAGES]; +MEMORY_ReadHandler ReadHandlerTable[MAX_PAGES]; +MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES]; -EMM_Handle EMM_Handles[EMM_HANDLECOUNT]; -PageEntry * PageEntries[MEM_MAXSIZE*1024*16]; /* Number of pages */ -Bit8u * memory=0; +/* Page handlers only work in lower memory */ +#define LOW_PAGE_LIMIT PAGE_COUNT(1024*1024) +#define MAX_PAGE_LIMIT PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024) -bool MEMORY_TestSpecial(PhysOff off) { - return (PageEntries[off >> 12]>0); -} - -void MEMORY_SetupHandler(Bit32u page,Bit32u pages,PageEntry * entry) { - for (Bit32u i=page;i>2);c++) { @@ -59,7 +46,7 @@ void MEM_BlockRead(PhysOff off,void * data,Bitu size) { } } -void MEM_BlockWrite(PhysOff off,void * data,Bitu size) { +void MEM_BlockWrite(PhysPt off,void * data,Bitu size) { Bitu c; Bit8u * idata=(Bit8u *)data; for (c=1;c<=(size>>2);c++) { @@ -72,7 +59,7 @@ void MEM_BlockWrite(PhysOff off,void * data,Bitu size) { } } -void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size) { +void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size) { Bitu c; for (c=1;c<=(size>>2);c++) { mem_writed(dest,mem_readd(src)); @@ -82,11 +69,9 @@ void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size) { mem_writeb(dest,mem_readb(src)); dest+=1;src+=1; } - - }; -void MEM_StrCopy(PhysOff off,char * data,Bitu size) { +void MEM_StrCopy(PhysPt off,char * data,Bitu size) { Bit8u c; while ((c=mem_readb(off)) && size) { *data=c; @@ -95,205 +80,167 @@ void MEM_StrCopy(PhysOff off,char * data,Bitu size) { *data='\0'; } - - - -/* TODO Maybe check for page boundaries but that would be wasting lot's of time */ -void mem_writeb(PhysOff off,Bit8u val) { - PageEntry * entry=PageEntries[off >> 12]; - if (!entry) { writeb(memory+off,val);return; } - switch (entry->type) { - case MEMORY_RELOCATE: - writeb(entry->relocate+(off-entry->base),val); - break; - case MEMORY_HANDLER: - entry->handler.write(off-entry->base,val); - break; - default: - E_Exit("Write to Illegal Memory Address %4x",off); - } -} - -void mem_writew(PhysOff off,Bit16u val) { - PageEntry * entry=PageEntries[off >> 12]; - if (!entry) { writew(memory+off,val);return; } - switch (entry->type) { - case MEMORY_RELOCATE: - writew(entry->relocate+(off-entry->base),val); - break; - case MEMORY_HANDLER: - entry->handler.write(off-entry->base,(val & 0xFF)); - entry->handler.write(off-entry->base+1,(val >> 8)); - break; - default: - E_Exit("Write to Illegal Memory Address %4x",off); - } -} - -void mem_writed(PhysOff off,Bit32u val) { - PageEntry * entry=PageEntries[off >> 12]; - if (!entry) { writed(memory+off,val);return; } - switch (entry->type) { - case MEMORY_RELOCATE: - writed(entry->relocate+(off-entry->base),val); - break; - case MEMORY_HANDLER: - entry->handler.write(off-entry->base, (Bit8u)(val & 0xFF)); - entry->handler.write(off-entry->base+1,(Bit8u)(val >> 8) & 0xFF); - entry->handler.write(off-entry->base+2,(Bit8u)(val >> 16) & 0xFF); - entry->handler.write(off-entry->base+3,(Bit8u)(val >> 24) & 0xFF); - break; - default: - E_Exit("Write to Illegal Memory Address %4x",off); - } -} - -Bit8u mem_readb(PhysOff off) { - PageEntry * entry=PageEntries[off >> 12]; - if (!entry) { return readb(memory+off);} - switch (entry->type) { - case MEMORY_RELOCATE: - return readb(entry->relocate+(off-entry->base)); - case MEMORY_HANDLER: - return entry->handler.read(off-entry->base); - break; - default: - E_Exit("Read from Illegal Memory Address %4x",off); - } - return 0; /* Keep compiler happy */ -} - -Bit16u mem_readw(PhysOff off) { - PageEntry * entry=PageEntries[off >> 12]; - if (!entry) { return readw(memory+off);} - switch (entry->type) { - case MEMORY_RELOCATE: - return readw(entry->relocate+(off-entry->base)); - case MEMORY_HANDLER: - return entry->handler.read(off-entry->base) | - (entry->handler.read(off-entry->base+1) << 8); - break; - default: - E_Exit("Read from Illegal Memory Address %4x",off); - } - return 0; /* Keep compiler happy */ -} - -Bit32u mem_readd(PhysOff off) { - PageEntry * entry=PageEntries[off >> 12]; - if (!entry) { return readd(memory+off);} - switch (entry->type) { - case MEMORY_RELOCATE: - return readd(entry->relocate+(off-entry->base)); - case MEMORY_HANDLER: - return entry->handler.read(off-entry->base) | - (entry->handler.read(off-entry->base+1) << 8) | - (entry->handler.read(off-entry->base+2) << 16)| - (entry->handler.read(off-entry->base+3) << 24); - break; - default: - E_Exit("Read from Illegal Memory Address %4x",off); - } - return 0; /* Keep compiler happy */ -} - -/* The EMM Allocation Part */ - -/* If this returns 0 we got and error since 0 is always taken */ -static Bit16u EMM_GetFreeHandle(void) { - Bit16u i=0; - while (i*maxblock) *maxblock=EMM_Handles[index].size; - *total+=EMM_Handles[index].size; - } - if (EMM_Handles[index].next) index=EMM_Handles[index].next; - else break; +/* Could only be called when the pt host entry is 0 ah well :) */ +static Bit8u Default_ReadHandler(PhysPt pt) { + return readb(WriteHostTable[pt >> PAGE_SHIFT]+pt); +} +static void Default_WriteHandler(PhysPt pt,Bit8u val) { + writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); +} + + +void MEM_SetupPageHandlers(Bitu startpage,Bitu pages,MEMORY_ReadHandler read,MEMORY_WriteHandler write) { + if (startpage+pages>=LOW_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); + for (Bitu i=startpage;isize) { - Bit16u newindex=EMM_GetFreeHandle(); - EMM_Handles[newindex].active=true; - EMM_Handles[newindex].phys_base=EMM_Handles[newindex].phys_base+size*4096; - EMM_Handles[newindex].size=EMM_Handles[index].size-size; - EMM_Handles[newindex].free=true; - EMM_Handles[newindex].next=EMM_Handles[index].next; - EMM_Handles[index].next=newindex; - EMM_Handles[index].free=false; - EMM_Handles[index].size=size; - *handle=index; - break; - } - } - if (EMM_Handles[index].next) index=EMM_Handles[index].next; - else break; + +void MEM_ClearPageHandlers(Bitu startpage,Bitu pages) { + if (startpage+pages>=LOW_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); + for (Bitu i=startpage;i=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); + HostPt base=(HostPt)(data)-startpage*PAGE_SIZE; + if (!base) LOG_DEBUG("MEMORY:Unlucky memory allocation"); + for (Bitu i=startpage;i=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); + for (Bitu i=startpage;i> 8) & 0xff) ); +} + +static void HandlerWrited(Bitu page,PhysPt pt,Bit32u val) { + WriteHandlerTable[page](pt+0,(Bit8u)(val & 0xff)); + WriteHandlerTable[page](pt+1,(Bit8u)((val >> 8) & 0xff) ); + WriteHandlerTable[page](pt+2,(Bit8u)((val >> 16) & 0xff) ); + WriteHandlerTable[page](pt+3,(Bit8u)((val >> 24) & 0xff) ); +} + +void mem_writeb(PhysPt pt,Bit8u val) { + if (WriteHostTable[pt >> PAGE_SHIFT]) writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); + else { + WriteHandlerTable[pt >> PAGE_SHIFT](pt,val); + } +} + +void mem_writew(PhysPt pt,Bit16u val) { + if (!WriteHostTable[pt >> PAGE_SHIFT]) { +// HandlerWritew(pt >> PAGE_SHIFT,pt,val); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); + } else writew(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); +} + +void mem_writed(PhysPt pt,Bit32u val) { + if (!WriteHostTable[pt >> PAGE_SHIFT]) { +// HandlerWrited(pt >> PAGE_SHIFT,pt,val); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+2,(Bit8u)((val >> 16) & 0xff) ); + WriteHandlerTable[pt >> PAGE_SHIFT](pt+3,(Bit8u)((val >> 24) & 0xff) ); + } else writed(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); } -PageEntry HMA_PageEntry; +static Bit16u HandlerReadw(Bitu page,PhysPt pt) { + return (ReadHandlerTable[page](pt+0)) | + (ReadHandlerTable[page](pt+1)) << 8; +} + +static Bit32u HandlerReadd(Bitu page,PhysPt pt) { + return (ReadHandlerTable[page](pt+0)) | + (ReadHandlerTable[page](pt+1)) << 8 | + (ReadHandlerTable[page](pt+2)) << 16 | + (ReadHandlerTable[page](pt+3)) << 24; +} + +Bit8u mem_readb(PhysPt pt) { + if (ReadHostTable[pt >> PAGE_SHIFT]) return readb(ReadHostTable[pt >> PAGE_SHIFT]+pt); + else { + return ReadHandlerTable[pt >> PAGE_SHIFT](pt); + } +} + +Bit16u mem_readw(PhysPt pt) { + if (!ReadHostTable[pt >> PAGE_SHIFT]) { +// return HandlerReadw(pt >> PAGE_SHIFT,pt); + return + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8; + } else return readw(ReadHostTable[pt >> PAGE_SHIFT]+pt); +} + +Bit32u mem_readd(PhysPt pt){ + if (ReadHostTable[pt >> PAGE_SHIFT]) return readd(ReadHostTable[pt >> PAGE_SHIFT]+pt); + else { +// return HandlerReadd(pt >> PAGE_SHIFT,pt); + return + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8 | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+2)) << 16 | + (ReadHandlerTable[pt >> PAGE_SHIFT](pt+3)) << 24; + } +} +#endif + + void MEM_Init(void) { - memset((void *)&PageEntries,0,sizeof(PageEntries)); - memory=(Bit8u *)malloc(memsize*1024*1024); + /* Init all tables */ + Bitu i; + i=MAX_PAGES; + for (i=0;i1) { - EMM_Handles[1].size=(memsize-1)*256-16; - } else { - EMM_Handles[0].size=0;; - } - EMM_Handles[1].active=true; - EMM_Handles[1].free=true; - EMM_Handles[1].phys_base=0x110000; -}; + /* Setup tables for first mb */ + MEM_SetupMapping(0,PAGE_COUNT(1024*1024),memory); + /* Setup tables for HMA Area */ + MEM_SetupMapping(PAGE_COUNT(1024*1024),PAGE_COUNT(64*1024),memory); +} diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index 5b1c0f2..6962c39 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -49,7 +49,7 @@ enum { MODE_ADPCM_4S }; -#ifdef DEBUG_SBLASTER +#if DEBUG_SBLASTER #define SB_DEBUG LOG_DEBUG #else #define SB_DEBUG @@ -75,8 +75,11 @@ struct SB_INFO { Bit8u data_out[DSP_BUFSIZE]; Bit8u data_out_pos; Bit8u data_out_used; - Bit8u dac_data[DSP_DACSIZE]; - Bit32u dac_used; + struct { + Bit8u data[DSP_DACSIZE]; + Bitu used; + Bit8u last; + } dac; Bit8u test_register; /*ADPCM Part */ Bits adpcm_reference; @@ -175,7 +178,7 @@ static void DSP_StartDMATranfser(Bit8u mode) { break; case MODE_ADPCM_4S: - MIXER_SetFreq(sb.chan,sb.freq*2); + MIXER_SetFreq(sb.chan,sb.freq); SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total); break; @@ -204,7 +207,8 @@ static void DSP_Reset(void) { sb.cmd_len=0; sb.cmd_in_pos=0; sb.use_time_constant=false; - sb.dac_used=0; + sb.dac.used=0; + sb.dac.last=0x80; e2_value=0xaa; e2_count=0; DSP_HaltDMA(); @@ -229,8 +233,8 @@ static void DSP_DoCommand(void) { switch (sb.cmd) { case 0x10: /* Direct DAC */ sb.mode=MODE_DAC; - if (sb.dac_used0) { - *(stream++)=sb.dac_data[dac_pos>>16]; - dac_pos+=dac_add; + if (sb.dac.used) { + Bitu dac_add=(sb.dac.used<<16)/len; + Bitu dac_pos=0; + while (len-->0) { + *(stream++)=sb.dac.data[dac_pos>>16]; + dac_pos+=dac_add; + } + dac_pos-=dac_add; + sb.dac.last=sb.dac.data[dac_pos>>16]; + sb.dac.used=0; + } else { + memset(stream,sb.dac.last,len); } } - sb.dac_used=0; - sb.mode=MODE_NONE; break; case MODE_PCM_8A: - DMA_8_Read(sb.dma,stream,(Bit16u)len); - if (sb.samples_left>len) { - sb.samples_left-=len; - } else { - if (len>(sb.samples_total+sb.samples_left)) sb.samples_left=sb.samples_total; - else sb.samples_left=sb.samples_total+sb.samples_left-len; - PIC_ActivateIRQ(sb.irq); + { + Bit16u read=DMA_8_Read(sb.dma,stream,(Bit16u)len); + if (sb.samples_left>read) { + sb.samples_left-=read; + } else { + if (read>(sb.samples_total+sb.samples_left)) sb.samples_left=sb.samples_total; + else sb.samples_left=sb.samples_total+sb.samples_left-read; + PIC_ActivateIRQ(sb.irq); + } + if (read=len) { - DMA_8_Read(sb.dma,stream,(Bit16u)len); - sb.samples_left-=len; - } else if (sb.samples_left && (sb.samples_left=len) { + read=DMA_8_Read(sb.dma,stream,(Bit16u)len); + sb.samples_left-=read; + } else { + read=DMA_8_Read(sb.dma,stream,(Bit16u)sb.samples_left); + sb.samples_left=0; + } + if (read=dma_size) { - DMA_8_Read(sb.dma,decode_pos,(Bit16u)dma_size); - sb.samples_left-=dma_size; + read=DMA_8_Read(sb.dma,decode_pos,(Bit16u)dma_size); } else if (sb.samples_left0;i--) { *stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale); *stream++=decode_ADPCM_4_sample(*decode_pos++ ,sb.adpcm_reference,sb.adpcm_scale); @@ -501,7 +518,8 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) { sb.adpcm_remain=-1; } } - } + break; + } /* End switch */ } diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 1d866fc..d2af313 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -29,6 +29,8 @@ VGA_Type vga; Bit32u CGAWriteTable[256]; Bit32u ExpandTable[256]; +Bit32u Expand16Table[4][16]; +Bit32u Expand16BigTable[0x10000]; Bit32u FillTable[16]={ 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, @@ -37,8 +39,9 @@ Bit32u FillTable[16]={ 0xffff0000,0xffff00ff,0xffffff00,0xffffffff }; -static PageEntry VGA_PageEntry; + +void VGA_Render_GFX_2(Bit8u * * data); void VGA_Render_GFX_4(Bit8u * * data); void VGA_Render_GFX_16(Bit8u * * data); void VGA_Render_GFX_256C(Bit8u * * data); @@ -47,8 +50,7 @@ void VGA_Render_TEXT_16(Bit8u * * data); void VGA_FindSettings(void) { /* Sets up the correct memory handler from the vga.mode setting */ - MEMORY_ResetHandler(0xA0000/4096,128*1024/4096); - VGA_PageEntry.type=MEMORY_HANDLER; + MEM_ClearPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x20000)); /* Detect the kind of video mode this is */ if (vga.config.gfxmode) { if (vga.config.vga_enabled) { @@ -59,26 +61,20 @@ void VGA_FindSettings(void) { } else { /* 256 color unchained vga */ vga.mode=GFX_256U; - VGA_PageEntry.base=0xA0000; - VGA_PageEntry.handler.read=VGA_NormalReadHandler; - VGA_PageEntry.handler.write=VGA_GFX_256U_WriteHandler; - MEMORY_SetupHandler(0xA0000/4096,16,&VGA_PageEntry); + MEM_SetupPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x10000), + &VGA_NormalReadHandler,&VGA_GFX_256U_WriteHandler); } } else if (vga.config.cga_enabled) { /* 4 color cga */ //TODO Detect hercules modes, probably set them up in bios too - vga.mode=GFX_4; -// VGA_PageEntry.base=0xB8000; -// VGA_PageEntry.handler.read=VGA_GFX_4_ReadHandler; -// VGA_PageEntry.handler.write=VGA_GFX_4_WriteHandler; -// MEMORY_SetupHandler(0xB8000/4096,8,&VGA_PageEntry); + if (vga.config.pixel_double) vga.mode=GFX_4; + else vga.mode=GFX_2; + //TODO Maybe also use a page handler for cga mode } else { /* 16 color ega */ vga.mode=GFX_16; - VGA_PageEntry.base=0xA0000; - VGA_PageEntry.handler.read=VGA_NormalReadHandler; - VGA_PageEntry.handler.write=VGA_GFX_16_WriteHandler; - MEMORY_SetupHandler(0xA0000/4096,16,&VGA_PageEntry); + MEM_SetupPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x10000), + &VGA_NormalReadHandler,&VGA_GFX_16_WriteHandler); } } else { vga.mode=TEXT_16; @@ -119,6 +115,12 @@ static void VGA_DoResize(void) { pitch=width; renderer=&VGA_Render_GFX_4; break; + case GFX_2: + width<<=3; + height<<=1; + pitch=width; + renderer=&VGA_Render_GFX_2; + break; case TEXT_16: /* probably a 16-color text mode, got to detect mono mode somehow */ width<<=3; /* 8 bit wide text font */ @@ -144,22 +146,51 @@ void VGA_StartResize(void) { } - - void VGA_Init() { vga.draw.resizing=false; VGA_SetupMemory(); VGA_SetupMisc(); VGA_SetupDAC(); - VGA_SetupCRTC(); VGA_SetupGFX(); VGA_SetupSEQ(); VGA_SetupAttr(); /* Generate tables */ - Bit32u i; + Bitu i,j; for (i=0;i<256;i++) { ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24); CGAWriteTable[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24); } + for (j=0;j<4;j++) { + for (i=0;i<16;i++) { + Expand16Table[j][i] = + ((i & 1) ? 1 << (24 + j) : 0) | + ((i & 2) ? 1 << (16 + j) : 0) | + ((i & 4) ? 1 << (8 + j) : 0) | + ((i & 8) ? 1 << j : 0); + } + } + for (i=0;i<0x10000;i++) { + Bit32u val=0; + if (i & 0x1) val|=0x1 << 24; + if (i & 0x2) val|=0x1 << 16; + if (i & 0x4) val|=0x1 << 8; + if (i & 0x8) val|=0x1 << 0; + + if (i & 0x10) val|=0x4 << 24; + if (i & 0x20) val|=0x4 << 16; + if (i & 0x40) val|=0x4 << 8; + if (i & 0x80) val|=0x4 << 0; + + if (i & 0x100) val|=0x2 << 24; + if (i & 0x200) val|=0x2 << 16; + if (i & 0x400) val|=0x2 << 8; + if (i & 0x800) val|=0x2 << 0; + + if (i & 0x1000) val|=0x8 << 24; + if (i & 0x2000) val|=0x8 << 16; + if (i & 0x4000) val|=0x8 << 8; + if (i & 0x8000) val|=0x8 << 0; + Expand16BigTable[i]=val; + } } diff --git a/src/hardware/vga.h b/src/hardware/vga.h index bd2985a..d43dc8e 100644 --- a/src/hardware/vga.h +++ b/src/hardware/vga.h @@ -51,6 +51,7 @@ typedef struct { bool vline_double; Bit8u vline_height; + bool pixel_double; /* Pixel Scrolling */ Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ Bit8u hlines_skip; @@ -64,11 +65,14 @@ typedef struct { Bit8u color_compare; Bit8u data_rotate; Bit8u raster_op; - Bit8u enable_set_reset; - Bit8u set_reset; Bit32u full_bit_mask; Bit32u full_map_mask; + Bit32u full_not_map_mask; + Bit32u full_set_reset; + Bit32u full_not_enable_set_reset; + Bit32u full_enable_set_reset; + Bit32u full_enable_and_set_reset; } VGA_Config; @@ -211,17 +215,14 @@ void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu next_line); void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line); void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line); void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line); +void VGA_DrawGFX2_Full(Bit8u * bitdata,Bitu next_line); /* The Different Memory Read/Write Handlers */ Bit8u VGA_NormalReadHandler(Bit32u start); -void VGA_NormalWriteHandler(Bit32u start,Bit8u val); void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val); void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val); void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val); -Bit8u VGA_ChainedReadHandler(Bit32u start); -void VGA_ChainedWriteHandler(Bit32u start,Bit8u val); - Bit8u VGA_GFX_4_ReadHandler(Bit32u start); @@ -246,10 +247,19 @@ extern VGA_Type vga; extern Bit8u vga_rom_8[256 * 8]; extern Bit8u vga_rom_14[256 * 14]; extern Bit8u vga_rom_16[256 * 16]; -//extern Bit8u vga_buffer[1024*1024]; + extern Bit32u ExpandTable[256]; extern Bit32u FillTable[16]; extern Bit32u CGAWriteTable[256]; +extern Bit32u Expand16Table[4][16]; +extern Bit32u Expand16BigTable[0x10000]; + +#if DEBUG_VGA +#define LOG_VGA LOG_DEBUG +#else +#define LOG_VGA +#endif + #endif diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index 4b0473f..3d4c6b9 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -129,6 +129,7 @@ void write_p3c0(Bit32u port,Bit8u val) { } Bit8u read_p3c1(Bit32u port) { + vga.internal.attrindex=false; switch (attr(index)) { /* Palette */ case 0x00: case 0x01: case 0x02: case 0x03: diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index 99f1ac1..020866c 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -28,6 +28,11 @@ void write_p3d4(Bit32u port,Bit8u val) { crtc(index)=val; } +Bit8u read_p3d4(Bit32u port) { + return crtc(index); +} + + void write_p3d5(Bit32u port,Bit8u val) { switch(crtc(index)) { case 0x00: /* Horizontal Total Register */ @@ -37,7 +42,7 @@ void write_p3d5(Bit32u port,Bit8u val) { case 0x01: /* Horizontal Display End Register */ crtc(horizontal_display_end)=val; vga.config.hdisplayend=val+1; - VGA_FindSettings(); + VGA_StartResize(); /* 0-7 Number of Character Clocks Displayed -1 */ break; case 0x02: /* Start Horizontal Blanking Register */ @@ -78,8 +83,8 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x07: /* Overflow Register */ crtc(overflow)=val; - vga.config.vdisplayend=(vga.config.vdisplayend&0xFF)|((val&2)<<7)|((val&64)<<2); - VGA_FindSettings(); + vga.config.vdisplayend=(vga.config.vdisplayend&0xFF)|(((val>>1) & 1)<<8)|(((val>>6) & 1)<<9); + VGA_StartResize(); /* 0 Bit 8 of Vertical Total (3d4h index 6) 1 Bit 8 of Vertical Display End (3d4h index 12h) @@ -108,7 +113,7 @@ void write_p3d5(Bit32u port,Bit8u val) { crtc(maximum_scan_line)=val; vga.config.vline_double=(val & 128)>1; vga.config.vline_height=(val & 0xf); - VGA_FindSettings(); + VGA_StartResize(); /* 0-4 Number of scan lines in a character row -1. In graphics modes this is the number of times (-1) the line is displayed before passing on to @@ -183,7 +188,7 @@ void write_p3d5(Bit32u port,Bit8u val) { case 0x12: /* Vertical Display End Register */ crtc(vertical_display_end)=val; vga.config.vdisplayend=(vga.config.vdisplayend & 0x300)|val; - VGA_FindSettings(); + VGA_StartResize(); /* 0-7 Lower 8 bits of Vertical Display End. The display ends when the line counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1. @@ -193,7 +198,7 @@ void write_p3d5(Bit32u port,Bit8u val) { case 0x13: /* Offset register */ crtc(offset)=val; vga.config.scan_len=val; - VGA_FindSettings(); + VGA_StartResize(); /* 0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for word mode and 8 for Double Word mode. @@ -317,16 +322,4 @@ Bit8u read_p3d5(Bit32u port) { -void VGA_SetupCRTC(void) { - IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select"); - IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register"); - IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register"); - -// IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select"); -// IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register"); -// IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register"); - - - -} diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index b161c86..e6a5dcd 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.cpp @@ -55,6 +55,12 @@ enum {DAC_READ,DAC_WRITE}; static void write_p3c6(Bit32u port,Bit8u val) { if (val!=0xff) LOG_ERROR("VGA:Pel Mask not 0xff"); + vga.dac.pel_mask=val; +} + + +static Bit8u read_p3c6(Bit32u port) { + return vga.dac.pel_mask; } @@ -151,6 +157,7 @@ void VGA_SetupDAC(void) { /* Setup the DAC IO port Handlers */ IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask"); + IO_RegisterReadHandler(0x3c6,read_p3c6,"PEL Mask"); IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode"); IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode"); IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data"); diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index c8f859f..2d07ba3 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -23,6 +23,11 @@ /* This Should draw a complete 16 colour screen */ +void VGA_Render_GFX_2(Bit8u * * data) { + *data=vga.buffer; + VGA_DrawGFX2_Full(vga.buffer,vga.draw.width); + vga.config.retrace=true; +} void VGA_Render_GFX_4(Bit8u * * data) { *data=vga.buffer; @@ -47,16 +52,43 @@ void VGA_Render_GFX_256C(Bit8u * * data) { void VGA_Render_TEXT_16(Bit8u * * data) { *data=vga.buffer; - VGA_DrawTEXT(vga.buffer,vga.draw.width); + if (!vga.draw.resizing) VGA_DrawTEXT(vga.buffer,vga.draw.width); + vga.config.retrace=true; +} + +void VGA_DrawGFX2_Full(Bit8u * bitdata,Bitu pitch) { + Bit8u * reader=HostMake(0xB800,0); + Bit8u * draw; + for (Bitu y=0;y>3;x++) { + Bit8u val=*(tempread++); + *(draw+0)=(val>>7)&1; + *(draw+1)=(val>>6)&1; + *(draw+2)=(val>>5)&1; + *(draw+3)=(val>>4)&1; + *(draw+4)=(val>>3)&1; + *(draw+5)=(val>>2)&1; + *(draw+6)=(val>>1)&1; + *(draw+7)=(val>>0)&1; + draw+=8; + } + bitdata+=pitch; + }; vga.config.retrace=true; } - -void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line) { - //TODO use vga memory handler - Bit8u * reader=real_host(0xB800,0); +void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu pitch) { + Bit8u * reader=HostMake(0xB800,0); Bit8u * draw; for (Bitu y=0;y>2;x++) { Bit8u val=*(tempread++); -/* - *(draw+0)=(val>>6)&3; - *(draw+1)=(val>>4)&3; - *(draw+2)=(val>>2)&3; - *(draw+3)=(val)&3; - draw+=4; -*/ *(Bit32u *)draw=CGAWriteTable[val]; draw+=4; } - //TODO use scanline length and dword mode crap - bitdata+=next_line; + bitdata+=pitch; }; vga.config.retrace=true; } -void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line) { +/* Draw the screen using the lookup buffer */ +//TODO include split screen or something +void VGA_DrawGFX16_Fast(Bit8u * bitdata,Bitu next_line) { Bit8u * reader=&vga.buffer[vga.config.display_start*8+vga.config.pel_panning]; for (Bitu y=0;y>2;x++) { @@ -108,28 +133,26 @@ void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line) { } xreader++; } - //TODO use scanline length and dword mode crap yreader+=vga.config.scan_len*2; bitdata+=next_line; }; vga.config.retrace=true; }; -void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu next_line) { +void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu pitch) { /* For now just copy 64 kb of memory with pitch support */ Bit8u * reader=memory+0xa0000; for (Bitu y=0;y=vga.draw.width) return; if ((vga.draw.cursor_row*16)>=vga.draw.height) return; - Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*vga.draw.width+vga.draw.cursor_col*8; + Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*pitch+vga.draw.cursor_col*8; if (vga.draw.cursor_count>8) { for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15; } diff --git a/src/hardware/vga_gfx.cpp b/src/hardware/vga_gfx.cpp index ddbb133..ff7b6a1 100644 --- a/src/hardware/vga_gfx.cpp +++ b/src/hardware/vga_gfx.cpp @@ -36,7 +36,9 @@ void write_p3cf(Bit32u port,Bit8u val) { switch (gfx(index)) { case 0: /* Set/Reset Register */ gfx(set_reset)=val & 0x0f; - vga.config.set_reset=val & 0x0f; + vga.config.full_set_reset=FillTable[val & 0x0f]; + vga.config.full_enable_and_set_reset=vga.config.full_set_reset & + vga.config.full_enable_set_reset; /* 0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to display memory will set all the bits in plane 0 of the byte to this @@ -50,15 +52,10 @@ void write_p3cf(Bit32u port,Bit8u val) { break; case 1: /* Enable Set/Reset Register */ gfx(enable_set_reset)=val & 0x0f; - vga.config.enable_set_reset=val & 0x0f; - /* - 0 If set enables Set/reset of plane 0 in Write Mode 0. - 1 Same for plane 1. - 2 Same for plane 2. - 3 Same for plane 3. - */ -// LOG_DEBUG("Enable Set Reset = %2X",val); - break; + vga.config.full_enable_set_reset=FillTable[val & 0x0f]; + vga.config.full_not_enable_set_reset=~vga.config.full_enable_set_reset; + vga.config.full_enable_and_set_reset=vga.config.full_set_reset & + vga.config.full_enable_set_reset; case 2: /* Color Compare Register */ gfx(color_compare)=val & 0x0f; /* diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index ffd2f0a..c0ed822 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -35,7 +35,8 @@ void VGA_ChainedWriteHandler(Bit32u start,Bit8u val) { }; -Bit8u VGA_NormalReadHandler(Bit32u start) { +Bit8u VGA_NormalReadHandler(PhysPt start) { + start-=0xa0000; vga.latch.d=vga.mem.latched[start].d; switch (vga.config.read_mode) { case 0: @@ -49,7 +50,7 @@ Bit8u VGA_NormalReadHandler(Bit32u start) { } //Nice one from DosEmu -INLINE Bit32u RasterOp(Bit32u input,Bit32u mask) { +INLINE static Bit32u RasterOp(Bit32u input,Bit32u mask) { switch (vga.config.raster_op) { case 0x00: /* None */ return (input & mask) | (vga.latch.d & ~mask); @@ -63,11 +64,39 @@ INLINE Bit32u RasterOp(Bit32u input,Bit32u mask) { return 0; } +INLINE static Bit32u ModeOperation(Bit8u val) { + Bit32u full; + switch (vga.config.write_mode) { + case 0x00: + // Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + full=ExpandTable[val]; + full=(full & vga.config.full_not_enable_set_reset) | vga.config.full_enable_and_set_reset; + full=RasterOp(full,vga.config.full_bit_mask); + break; + case 0x01: + // Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode. + full=vga.latch.d; + break; + case 0x02: + //Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + full=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask); + break; + case 0x03: + // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask); + break; + default: + LOG_ERROR("VGA:Unsupported write mode %d",vga.config.write_mode); + } + return full; +} + Bit8u VGA_GFX_4_ReadHandler(Bit32u start) { return vga.mem.linear[start]; } void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) { + start-=0xa0000; vga.mem.linear[start]=val; Bitu line=start / 320; Bitu x=start % 320; @@ -80,114 +109,45 @@ void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) { } void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) { - VGA_Latch new_latch; - Bitu bit_mask; - switch (vga.config.write_mode) { - case 0x00: - // Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. -// val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate)); - //Todo could also include the rotation in the table :) - new_latch.d=ExpandTable[val]; - { - Bit32u resetmask=FillTable[vga.config.enable_set_reset]; - new_latch.d=(new_latch.d & ~resetmask) | ( FillTable[vga.config.set_reset] & resetmask); - }; - new_latch.d=RasterOp(new_latch.d,vga.config.full_bit_mask); - bit_mask=vga.gfx.bit_mask; - break; - case 0x01: - // Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode. - new_latch.d=vga.latch.d; - bit_mask=0xff; - break; - case 0x02: - //Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - new_latch.d=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask); - bit_mask=vga.gfx.bit_mask; - break; - case 0x03: - // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - new_latch.d=ExpandTable[val]; - new_latch.d&=vga.config.full_bit_mask; //Dunno would anyone use this seems a bit pointless - bit_mask=new_latch.b[0]; - new_latch.d=RasterOp(FillTable[vga.config.set_reset],new_latch.d); - break; - default: - LOG_ERROR("VGA:Unsupported write mode %d",vga.config.write_mode); - } + start-=0xa0000; + Bit32u data=ModeOperation(val); /* Update video memory and the pixel buffer */ VGA_Latch pixels; pixels.d=vga.mem.latched[start].d; - pixels.d&=~vga.config.full_map_mask; - pixels.d|=(new_latch.d & vga.config.full_map_mask); + pixels.d&=vga.config.full_not_map_mask; + pixels.d|=(data & vga.config.full_map_mask); vga.mem.latched[start].d=pixels.d; Bit8u * write_pixels=&vga.buffer[start<<3]; -#if 1 - Bit8u sel=128; - do { - if (bit_mask & sel) { - Bitu color; - color=0; - if (pixels.b[0] & sel) color|=1; - if (pixels.b[1] & sel) color|=2; - if (pixels.b[2] & sel) color|=4; - if (pixels.b[3] & sel) color|=8; - *write_pixels=color; - *(write_pixels+512*1024)=color; - } - write_pixels++; - sel>>=1; - } while (sel); -#else -#include "ega-switch.h" -#endif + Bit32u colors0_3, colors4_7; + VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; + colors0_3 = + Expand16Table[0][temp.b[0]] | + Expand16Table[1][temp.b[1]] | + Expand16Table[2][temp.b[2]] | + Expand16Table[3][temp.b[3]]; + *(Bit32u *)write_pixels=colors0_3; + *(Bit32u *)(write_pixels+512*1024)=colors0_3; + temp.d=pixels.d & 0x0f0f0f0f; + colors4_7 = + Expand16Table[0][temp.b[0]] | + Expand16Table[1][temp.b[1]] | + Expand16Table[2][temp.b[2]] | + Expand16Table[3][temp.b[3]]; + *(Bit32u *)(write_pixels+4)=colors4_7; + *(Bit32u *)(write_pixels+512*1024+4)=colors4_7; } - - - void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val) { - VGA_Latch new_latch; - switch (vga.config.write_mode) { - case 0x00: - /* This should be no problem with big or little endian */ - // Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. -// val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate)); - //Todo could also include the rotation in the table :) - new_latch.d=ExpandTable[val]; - { - Bit32u resetmask=FillTable[vga.config.enable_set_reset]; - new_latch.d=(new_latch.d & ~resetmask) | ( FillTable[vga.config.set_reset] & resetmask); - }; - new_latch.d=RasterOp(new_latch.d,vga.config.full_bit_mask); - break; - case 0x01: - // Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode. - new_latch.d=vga.latch.d; - break; - case 0x02: - //TODO this mode also has Raster op - //Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - new_latch.d=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask); - break; - case 0x03: - // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - new_latch.d=ExpandTable[val]; - new_latch.d&=vga.config.full_bit_mask; //Dunno would anyone use this seems a bit pointless - new_latch.d=RasterOp(FillTable[vga.config.set_reset],new_latch.d); - break; - default: - E_Exit("VGA:Unsupported write mode %d",vga.config.write_mode); - } + start-=0xa0000; + Bit32u data=ModeOperation(val); VGA_Latch pixels; pixels.d=vga.mem.latched[start].d; - pixels.d&=~vga.config.full_map_mask; - pixels.d|=(new_latch.d & vga.config.full_map_mask); + pixels.d&=vga.config.full_not_map_mask; + pixels.d|=(data & vga.config.full_map_mask); vga.mem.latched[start].d=pixels.d; vga.mem.latched[start+64*1024].d=pixels.d; - }; diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index c1d6f19..e2fa92e 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -24,7 +24,12 @@ static Bit8u flip=0; static Bit32u keep_vretrace; static bool keeping=false; -static Bit8u p3c2data; +static Bit8u p3c2data=0; + +void write_p3d4(Bit32u port,Bit8u val); +Bit8u read_p3d4(Bit32u port); +void write_p3d5(Bit32u port,Bit8u val); +Bit8u read_p3d5(Bit32u port); static Bit8u read_p3da(Bit32u port) { vga.internal.attrindex=false; @@ -45,26 +50,68 @@ static Bit8u read_p3da(Bit32u port) { if (flip>5) return 1; return 0; } -}; + /* + 0 Either Vertical or Horizontal Retrace active if set + 3 Vertical Retrace in progress if set + */ +} static void write_p3d8(Bit32u port,Bit8u val) { - return; + /* + 3 Vertical Sync Select. If set Vertical Sync to the monitor is the + logical OR of the vertical sync and the vertical display enable. + */ } static void write_p3c2(Bit32u port,Bit8u val) { p3c2data=val; + if (val & 1) { + IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select"); + IO_RegisterReadHandler(0x3d4,read_p3d4,"VGA:CRTC Index Select"); + IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register"); + IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register"); + IO_FreeWriteHandler(0x3b4); + IO_FreeReadHandler(0x3b4); + IO_FreeWriteHandler(0x3b5); + IO_FreeReadHandler(0x3b5); + + } else { + IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select"); + IO_RegisterReadHandler(0x3b4,read_p3d4,"VGA:CRTC Index Select"); + IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register"); + IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register"); + IO_FreeWriteHandler(0x3d4); + IO_FreeReadHandler(0x3d4); + IO_FreeWriteHandler(0x3d5); + IO_FreeReadHandler(0x3d5); + } + /* + 0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh. + 2-3 Clock Select. 0: 25MHz, 1: 28MHz + 5 When in Odd/Even modes Select High 64k bank if set + 6 Horizontal Sync Polarity. Negative if set + 7 Vertical Sync Polarity. Negative if set + Bit 6-7 indicates the number of lines on the display: + 1: 400, 2: 350, 3: 480 + Note: Set to all zero on a hardware reset. + Note: This register can be read from port 3CCh. + */ } -static Bit8u read_p3c2(Bit32u port) { + + +static Bit8u read_p3cc(Bit32u port) { return p3c2data; } void VGA_SetupMisc(void) { IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1"); -// IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Mode Control"); + IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1"); + + IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Feature Control Register"); IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output"); - IO_RegisterReadHandler(0x3c2,read_p3c2,"VGA Misc Output"); + IO_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output"); } diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index ce5e0cf..9a7aa0c 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -37,6 +37,8 @@ void write_p3c5(Bit32u port,Bit8u val) { break; case 1: /* Clocking Mode */ seq(clocking_mode)=val; + vga.config.pixel_double=(val & 8)>0; + VGA_FindSettings(); /* TODO Figure this out :) 0 If set character clocks are 8 dots wide, else 9. 2 If set loads video serializers every other character @@ -53,6 +55,7 @@ void write_p3c5(Bit32u port,Bit8u val) { case 2: /* Map Mask */ seq(map_mask)=val & 15; vga.config.full_map_mask=FillTable[val & 15]; + vga.config.full_not_map_mask=~vga.config.full_map_mask; /* 0 Enable writes to plane 0 if set 1 Enable writes to plane 1 if set diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 963fbb0..57466e7 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -101,6 +101,10 @@ static Bitu INT11_Handler(void) { static Bitu INT8_Handler(void) { /* Increase the bios tick counter */ mem_writed(BIOS_TIMER,mem_readd(BIOS_TIMER)+1); + /* decrease floppy motor timer */ + Bit8u val = mem_readb(BIOS_DISK_MOTOR_TIMEOUT); + if (val>0) mem_writeb(BIOS_DISK_MOTOR_TIMEOUT,val-1); + CALLBACK_RunRealInt(0x1c); IO_Write(0x20,0x20); return CBRET_NONE; @@ -141,6 +145,10 @@ static Bitu INT15_Handler(void) { LOG_WARN("Request BIOS Configuration INT 15 C0"); CALLBACK_SCF(true); break; + case 0x4f: /* BIOS - Keyboard intercept */ + /* Carry should be set but let's just set it just in case */ + CALLBACK_SCF(true); + 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"); diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index 3813c5b..da24f79 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -28,32 +28,6 @@ static BIOS_Disk * Floppys[2]; static BIOS_Disk * Harddisks[BIOS_MAX_DISK]; static Bit8u last_status; -static Bitu INT13_FullHandler(void) { - /* Check for disk numbers */ - BIOS_Disk * disk=Floppys[0]; - switch (reg_ah) { - case 0x00: - last_status=reg_ah=0; - break; - case 0x01: /* Get Status of last operation */ - reg_ah=last_status; - break; - case 0x02: /* Read Sectors into Memory */ - last_status=reg_ah=disk->Read_Sector(®_al,reg_dh,reg_ch,(reg_cl & 0x3f)-1,real_off(Segs[es].value,reg_bx)); - CALLBACK_SCF(false); - break; - case 0x03: /* Write Sectors from Memory */ - last_status=reg_ah=disk->Write_Sector(®_al,reg_dh,reg_ch,(reg_cl & 0x3f)-1,real_off(Segs[es].value,reg_bx)); - CALLBACK_SCF(false); - break; - default: - LOG_DEBUG("INT13:Illegal call %2X",reg_ah); - reg_ah=0xff; - CALLBACK_SCF(true); - } - return CBRET_NONE; -}; - static Bitu INT13_SmallHandler(void) { switch (reg_ah) { @@ -79,13 +53,7 @@ static Bitu INT13_SmallHandler(void) { void BIOS_SetupDisks(void) { /* TODO Start the time correctly */ call_int13=CALLBACK_Allocate(); -#ifdef C_IMAGE - Floppys[0]=new imageDisk("c:\\test.img"); - for (Bit32u i=0;i', '?',255,'*',255, ' ',255,0,0, 0,0,0,0, - 0,0,0,0, 255,255,0,0, 0,'-',0,255, 0,'+',0,0, - 0,0,0,0, 0 -}; -*/ - static void add_key(Bit16u code) { Bit16u start,end,head,tail,ttail; start=mem_readw(BIOS_KEYBOARD_BUFFER_START); @@ -151,10 +130,12 @@ static void add_key(Bit16u code) { head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); ttail=tail+2; - if (ttail>=end) ttail=start; + if (ttail>=end) { + ttail=start; + } /* Check for buffer Full */ //TODO Maybe beeeeeeep or something although that should happend when internal buffer is full - if (ttail==head) return; + if (ttail==head) return; real_writew(0x40,tail,code); mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,ttail); } diff --git a/src/ints/ems.cpp b/src/ints/ems.cpp index d10839c..d3b694d 100644 --- a/src/ints/ems.cpp +++ b/src/ints/ems.cpp @@ -18,6 +18,7 @@ #include +#include #include "dosbox.h" #include "callback.h" #include "mem.h" @@ -28,105 +29,396 @@ #include "dos_inc.h" -#define PAGEFRAME_SEG 0xe000 +#define EMM_PAGEFRAME 0xE000 +#define EMM_MAX_HANDLES 50 /* 255 Max */ +#define EMM_PAGE_SIZE (16*1024) +#define EMM_MAX_PAGES (C_MEM_EMS_SIZE * 1024 / 16 ) +#define EMM_MAX_PHYS 4 /* 4 16kb pages in pageframe */ -class device_EMS : public DOS_Device { +#define EMM_VERSION 0x40 + +#define NULL_HANDLE 0xffff +#define NULL_PAGE 0xffff + +/* EMM errors */ +#define EMM_NO_ERROR 0x00 +#define EMM_SOFT_MAL 0x80 +#define EMM_HARD_MAL 0x81 +#define EMM_INVALID_HANDLE 0x83 +#define EMM_FUNC_NOSUP 0x84 +#define EMM_OUT_OF_HANDLES 0x85 +#define EMM_OUT_OF_PHYS 0x87 +#define EMM_OUT_OF_LOG 0x88 +#define EMM_ZERO_PAGES 0x89 +#define EMM_LOG_OUT_RANGE 0x8a +#define EMM_ILL_PHYS 0x8b +#define EMM_PAGE_MAP_SAVED 0x8d +#define EMM_INVALID_SUB 0x8f +#define EMM_FEAT_NOSUP 0x91 +#define EMM_MOVE_OVLAP 0x92 +#define EMM_MOVE_OVLAPI 0x97 +#define EMM_NOT_FOUND 0xa0 + + +class device_EMM : public DOS_Device { public: - device_EMS(); - bool Read(Bit8u * data,Bit16u * size); - bool Write(Bit8u * data,Bit16u * size); - bool Seek(Bit32u * pos,Bit32u type); - bool Close(); - Bit16u GetInformation(void); + device_EMM(){name="EMMXXXX0";} + bool Read(Bit8u * data,Bit16u * size) { return false;} + bool Write(Bit8u * data,Bit16u * size){ + LOG_DEBUG("Write to ems device"); + return false; + } + bool Seek(Bit32u * pos,Bit32u type){return false;} + bool Close(){return false;} + Bit16u GetInformation(void){return 0x8093;} private: Bit8u cache; }; -bool device_EMS::Read(Bit8u * data,Bit16u * size) { - return false; -} - -bool device_EMS::Write(Bit8u * data,Bit16u * size) { - return false; -} - -bool device_EMS::Seek(Bit32u * pos,Bit32u type) { - return false; -} - -bool device_EMS::Close() { - return false; -} - -Bit16u device_EMS::GetInformation(void) { - return 0x8093; +struct EMM_Mapping { + Bit16u handle; + Bit16u page; }; -device_EMS::device_EMS() { - name="EMMXXXX0"; +struct EMM_Page { + void * memory; + Bit16u handle; + Bit16u next; +}; + +struct EMM_Handle { + Bit16u first_page; + Bit16u pages; + char name[9]; + bool saved_page_map; + EMM_Mapping page_map[EMM_MAX_PHYS]; +}; + +static EMM_Handle emm_handles[EMM_MAX_HANDLES]; +static EMM_Page emm_pages[EMM_MAX_PAGES]; +static EMM_Mapping emm_mappings[EMM_MAX_PHYS]; +Bitu call_int67; + +static Bit16u EMM_GetFreePages(void) { + Bit16u count=0; + for (Bitu index=0;index=EMM_MAX_HANDLES) {handle=NULL_HANDLE;return EMM_OUT_OF_HANDLES;} + } + /* Allocate the pages */ + Bit16u page=0;Bit16u last=NULL_PAGE; + emm_handles[handle].pages=pages; + while (pages) { + if (emm_pages[page].handle==NULL_HANDLE) { + emm_pages[page].handle=handle; + emm_pages[page].memory=malloc(EMM_PAGE_SIZE); + if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory"); + if (last!=NULL_PAGE) emm_pages[last].next=page; + else emm_handles[handle].first_page=page; + last=page; + pages--; + } else { + if (++page>=EMM_MAX_PAGES) E_Exit("EMM:Ran out of pages"); + } + } + return EMM_NO_ERROR; +} -PageEntry ems_entries[4]; +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; + /* Check for enough pages */ + if ((emm_handles[handle].pages+EMM_GetFreePages())0 && page_count>0) { + if (emm_pages[page].handle!=handle) E_Exit("EMM:Error illegal handle reference"); + last=page; + page=emm_pages[page].next; + pages--; + page_count--; + } + /* Free the rest of the handles */ + if (page_count && !pages) { + emm_handles[handle].pages-=page_count; + while (page_count>0) { + free(emm_pages[page].memory); + emm_pages[page].memory=0; + emm_pages[page].handle=NULL_HANDLE; + Bit16u next_page=emm_pages[page].next; + emm_pages[page].next=NULL_PAGE; + page=next_page;page_count--; + } + pages=emm_handles[handle].pages; + return EMM_NO_ERROR; + } + if (!page_count && pages) { + /* Allocate extra pages */ + emm_handles[handle].pages+=pages; + page=0; + while (pages) { + if (emm_pages[page].handle==NULL_HANDLE) { + emm_pages[page].handle=handle; + emm_pages[page].memory=malloc(EMM_PAGE_SIZE); + if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory"); + emm_pages[last].next=page; + last=page; + pages--; + } else { + if (++page>=EMM_MAX_PAGES) E_Exit("EMM:Ran out of pages"); + } + } + pages=emm_handles[handle].pages; + return EMM_NO_ERROR; + } + /* Size exactly the same as the original size */ + pages=emm_handles[handle].pages; + return EMM_NO_ERROR; +} + +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; + /* Check to do unmapping or mappning */ + if (log_page=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; + Bit16u page=emm_handles[handle].first_page; + Bit16u pages=emm_handles[handle].pages; + while (pages) { + free(emm_pages[page].memory); + emm_pages[page].memory=0; + emm_pages[page].handle=NULL_HANDLE; + Bit16u next_page=emm_pages[page].next; + emm_pages[page].next=NULL_PAGE; + page=next_page;pages--; + } + /* Reset handle */ + emm_handles[handle].first_page=NULL_PAGE; + emm_handles[handle].pages=0; + emm_handles[handle].saved_page_map=false; + memset(&emm_handles[handle].name,0,9); + return EMM_NO_ERROR; +} + +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; + /* Check for previous save */ + if (emm_handles[handle].saved_page_map) return EMM_PAGE_MAP_SAVED; + /* Copy the mappings over */ + for (Bitu i=0;i=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; + /* Check for previous save */ + if (!emm_handles[handle].saved_page_map) return EMM_INVALID_HANDLE; + /* Restore the mappings */ + emm_handles[handle].saved_page_map=false; + for (Bitu i=0;i>2; - reg_bx=total>>2; - reg_ah=0; - }; + reg_dx=EMM_MAX_PAGES; + reg_bx=EMM_GetFreePages(); + reg_ah=EMM_NO_ERROR; break; case 0x43: /* Get Handle and Allocate Pages */ - { - if (!reg_bx) { reg_ah=0x89;break; } - Bit16u handle; - EMM_Allocate(reg_bx*4,&handle); - if (handle) { - reg_ah=0; - reg_dx=handle; - } else { reg_ah=0x88; } - break; - } - case 0x44: /* Map Memory */ - { - if (reg_al>3) { reg_ah=0x8b;break; } - HostOff pagestart=memory+EMM_Handles[reg_dx].phys_base+reg_bx*16*1024; - ems_entries[reg_al].relocate=pagestart; - reg_ah=0; - break; - } - case 0x45: /* Release handle and free pages */ - EMM_Free(reg_dx); - reg_ah=0; - break; - case 0x46: /* Get EMM Version */ - reg_ah=0; - reg_al=0x32; //Only 3.2 support for now + reg_ah=EMM_AllocateMemory(reg_bx,reg_dx); break; - case 0x47: /* Save Mapping Context */ - LOG_ERROR("EMS:47:Save Mapping Context not supported"); - reg_ah=0x8c; + case 0x44: /* Map Expanded Memory Page */ + reg_ah=EMM_MapPage(reg_al,reg_dx,reg_bx); + break; + case 0x45: /* Release handle and free pages */ + reg_ah=EMM_ReleaseMemory(reg_dx); + break; + case 0x46: /* Get EMM Version */ + reg_ah=EMM_NO_ERROR; + reg_al=EMM_VERSION; + break; + case 0x47: /* Save Page Map */ + reg_ah=EMM_SavePageMap(reg_dx); + break; + case 0x48: /* Restore Page Map */ + reg_ah=EMM_RestorePageMap(reg_dx); + break; + case 0x4b: /* Get Handle Count */ + reg_bx=0; + for (i=0;i=EMM_MAX_HANDLES || emm_handles[reg_bx].first_page==NULL_PAGE) {reg_ah=EMM_INVALID_HANDLE;break;} + reg_bx=emm_handles[reg_dx].pages; + reg_ah=EMM_NO_ERROR; + break; + case 0x4d: /* Get Pages for all Handles */ + 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)); + reg_ah=EMM_NO_ERROR; + break; + case 0x01: /* Restore Page Map */ + MEM_BlockRead(SegPhys(ds)+reg_si,emm_mappings,sizeof(emm_mappings)); + reg_ah=EMM_RestoreMappingTable(); + break; + case 0x02: /* Save and Restore Page Map */ + MEM_BlockWrite(SegPhys(es)+reg_di,emm_mappings,sizeof(emm_mappings)); + MEM_BlockRead(SegPhys(ds)+reg_si,emm_mappings,sizeof(emm_mappings)); + reg_ah=EMM_RestoreMappingTable(); + break; + case 0x03: /* Get Page Map Array Size */ + reg_al=sizeof(emm_mappings); + reg_ah=EMM_NO_ERROR; + break; + default: + LOG_ERROR("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + reg_ah=EMM_FUNC_NOSUP; + break; + } + break; + case 0x50: // Map/Unmap multiple handle pages + reg_ah = EMM_NO_ERROR; + switch (reg_al) { + case 0x00: // use physical page numbers + { PhysPt data = SegPhys(ds)+reg_si; + for (int i=0; i>12,4,&ems_entries[i]); - } /* 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 - MEM_BlockWrite(real_phys(seg,0xa),emsname,strlen(emsname)+1); -/* Copy the callback piece into the beginning */ + MEM_BlockWrite(PhysMake(seg,0xa),emsname,strlen(emsname)+1); +/* Copy the callback piece into the beginning, and set the interrupt vector to it*/ char buf[16]; - MEM_BlockRead(real_phys(CB_SEG,call_int67<<4),buf,0xa); - MEM_BlockWrite(real_phys(seg,0),buf,0xa); - + MEM_BlockRead(PhysMake(CB_SEG,call_int67<<4),buf,0xa); + MEM_BlockWrite(PhysMake(seg,0),buf,0xa); RealSetVec(0x67,RealMake(seg,0)); +/* Clear handle and page tables */ + Bitu i; + for (i=0;i #include "dosbox.h" #include "bios.h" @@ -54,14 +53,15 @@ static Bitu INT10_Handler(void) { LOG_WARN("INT10:04:Ligthpen not supported"); break; case 0x05: /* Set Active Page */ - INT10_SetActivePage(reg_al); + if (reg_al & 0x80) LOG_DEBUG("Func %x",reg_al); + else INT10_SetActivePage(reg_al); break; case 0x06: /* Scroll Up */ //TODO Graphics mode scroll - INT10_ScrollUpWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); + INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,-reg_al,reg_bh,0xFF); break; case 0x07: /* Scroll Down */ - INT10_ScrollDownWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); + INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); break; case 0x08: /* Read character & attribute at cursor */ //TODO Check for GRAPH and then just return @@ -84,9 +84,7 @@ static Bitu INT10_Handler(void) { INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al); break; case 0x0E: /* Teletype OutPut */ - //TODO FIX - INT10_TeletypeOutput(reg_al,reg_bl,false,0); -// INT10_TeletypeOutput(reg_al,reg_bl,false,reg_bh); + INT10_TeletypeOutput(reg_al,reg_bl,false,reg_bh); break; case 0x0F: /* Get videomode */ reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); @@ -102,7 +100,7 @@ static Bitu INT10_Handler(void) { INT10_SetOverscanBorderColor(reg_bh); break; case 0x02: /* SET ALL PALETTE REGISTERS */ - INT10_SetAllPaletteRegisters(real_phys(Segs[es].value,reg_dx)); + INT10_SetAllPaletteRegisters(SegPhys(es)+reg_dx); break; case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */ INT10_ToggleBlinkingBit(reg_bl); @@ -114,19 +112,19 @@ static Bitu INT10_Handler(void) { INT10_GetOverscanBorderColor(®_bh); break; case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */ - INT10_GetAllPaletteRegisters(real_phys(Segs[es].value,reg_dx)); + INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx); break; case 0x10: /* SET INDIVIDUAL DAC REGISTER */ INT10_SetSingleDacRegister(reg_bl,reg_dh,reg_ch,reg_cl); break; case 0x12: /* SET BLOCK OF DAC REGISTERS */ - INT10_SetDACBlock(reg_bx,reg_cx,real_phys(Segs[es].value,reg_dx)); + INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); break; case 0x15: /* GET INDIVIDUAL DAC REGISTER */ INT10_GetSingleDacRegister(reg_bl,®_dh,®_ch,®_cl); break; case 0x17: /* GET BLOCK OF DAC REGISTER */ - INT10_GetDACBlock(reg_bx,reg_cx,real_phys(Segs[es].value,reg_dx)); + INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); break; default: LOG_WARN("INT10:10:Unhandled EGA/VGA Palette Function %2X",reg_al); @@ -139,7 +137,7 @@ static Bitu INT10_Handler(void) { case 0x00: /* interupt 0x1f vector */ { RealPt int_1f=RealGetVec(0x1f); - SetSegment_16(es,RealSeg(int_1f)); + SegSet16(es,RealSeg(int_1f)); reg_bp=RealOff(int_1f); reg_cx=8; } @@ -147,28 +145,28 @@ static Bitu INT10_Handler(void) { case 0x01: /* interupt 0x43 vector */ { RealPt int_43=RealGetVec(0x43); - SetSegment_16(es,RealSeg(int_43)); + SegSet16(es,RealSeg(int_43)); reg_bp=RealOff(int_43); reg_cx=8; } break; case 0x02: /* font 8x14 */ - SetSegment_16(es,RealSeg(int10_romarea.font_14)); + SegSet16(es,RealSeg(int10_romarea.font_14)); reg_bp=RealOff(int10_romarea.font_14); reg_cx=14; break; case 0x03: /* font 8x8 first 128 */ - SetSegment_16(es,RealSeg(int10_romarea.font_8_first)); + SegSet16(es,RealSeg(int10_romarea.font_8_first)); reg_bp=RealOff(int10_romarea.font_8_first); reg_cx=8; break; case 0x04: /* font 8x8 second 128 */ - SetSegment_16(es,RealSeg(int10_romarea.font_8_second)); + SegSet16(es,RealSeg(int10_romarea.font_8_second)); reg_bp=RealOff(int10_romarea.font_8_second); reg_cx=8; break; case 0x06: /* font 8x16 */ - SetSegment_16(es,RealSeg(int10_romarea.font_16)); + SegSet16(es,RealSeg(int10_romarea.font_16)); reg_bp=RealOff(int10_romarea.font_16); reg_cx=16; break; @@ -196,7 +194,7 @@ static Bitu INT10_Handler(void) { } break; case 0x13: /* Write String */ - INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,real_phys(Segs[es].value,reg_bp),reg_cx,reg_bh); + INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,SegPhys(es)+reg_bp,reg_cx,reg_bh); break; case 0x1A: /* Display Combination */ if (reg_al==0) { @@ -214,7 +212,7 @@ static Bitu INT10_Handler(void) { case 0x1B: /* functionality State Information */ switch (reg_bx) { case 0x0000: - INT10_GetFuncStateInformation(Segs[es].value,reg_di); + INT10_GetFuncStateInformation(SegPhys(es)+reg_di); reg_al=0x1B; break; default: @@ -262,7 +260,6 @@ static void INT10_InitVGA(void) { }; void INT10_StartUp(void) { - INT10_InitVGA(); /* Setup the INT 10 vector */ call_10=CALLBACK_Allocate(); diff --git a/src/ints/int10.h b/src/ints/int10.h index f7af321..41ae488 100644 --- a/src/ints/int10.h +++ b/src/ints/int10.h @@ -102,11 +102,15 @@ #define PLANAR4 0x05 #define LINEAR8 0x06 -// for SVGA -#define LINEAR15 0x07 -#define LINEAR16 0x08 -#define LINEAR24 0x09 -#define LINEAR32 0x0 +// for Tandy + +#define TANDY16 0x0A + + +#define LINEAR15 0x10 +#define LINEAR16 0x11 +#define LINEAR24 0x12 +#define LINEAR32 0x13 #define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1) @@ -167,19 +171,16 @@ inline Bit8u CURSOR_POS_ROW(Bit8u page) { void INT10_SetVideoMode(Bit8u mode); -void INT10_ScrollUpWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page); -void INT10_ScrollDownWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page); - +void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page); void INT10_SetActivePage(Bit8u page); -void INT10_GetFuncStateInformation(Bit16u seg,Bit16u off); - +void INT10_GetFuncStateInformation(PhysPt save); void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page); void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page); void INT10_ReadCharAttr(Bit16u * result,Bit8u page); void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr); -void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysOff string,Bit16u count,Bit8u page); +void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page); /* Graphics Stuff */ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color); @@ -189,15 +190,15 @@ VGAMODES * GetCurrentMode(void); /* Palette Group */ void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val); void INT10_SetOverscanBorderColor(Bit8u val); -void INT10_SetAllPaletteRegisters(PhysOff data); +void INT10_SetAllPaletteRegisters(PhysPt data); void INT10_ToggleBlinkingBit(Bit8u state); void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val); void INT10_GetOverscanBorderColor(Bit8u * val); -void INT10_GetAllPaletteRegisters(PhysOff data); +void INT10_GetAllPaletteRegisters(PhysPt data); void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue); void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue); -void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data); -void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysOff data); +void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data); +void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data); /* Sup Groups */ diff --git a/src/ints/int10_char.cpp b/src/ints/int10_char.cpp index 6c90fcb..1a0e5d4 100644 --- a/src/ints/int10_char.cpp +++ b/src/ints/int10_char.cpp @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /* Character displaying moving functions */ #include "dosbox.h" @@ -25,185 +24,143 @@ #include "inout.h" #include "int10.h" +static INLINE void PLANAR4_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { + PhysPt src,dest;Bitu copy; + dest=base+(curmode->twidth*rnew)*curmode->cheight+cleft; + src=base+(curmode->twidth*rold)*curmode->cheight+cleft; + Bitu nextline=curmode->twidth; + /* Setup registers correctly */ + IO_Write(0x3ce,5);IO_Write(0x3cf,1); /* Memory transfer mode */ + IO_Write(0x3c4,2);IO_Write(0x3c5,0xf); /* Enable all Write planes */ + /* Do some copying */ + Bitu rowsize=(cright-cleft); + copy=curmode->cheight; + for (;copy>0;copy--) { + for (Bitu x=0;xtwidth+cleft)*2; + dest=base+(rnew*curmode->twidth+cleft)*2; + MEM_BlockCopy(dest,src,(cright-cleft)*2); +} + +static INLINE void PLANAR4_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) { + /* Set Bitmask / Color / Full Set Reset */ + 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; + Bitu nextline=curmode->twidth; + Bitu copy=curmode->cheight; Bitu rowsize=(cright-cleft); + for (;copy>0;copy--) { + for (Bitu x=0;xtwidth+cleft)*2; + Bit16u fill=(attr<<8)+' '; + for (Bit8u x=0;x<(cright-cleft);x++) { + mem_writew(dest,fill); + dest+=2; + } + +} + + +void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page) { + + /* Do some range checking */ BIOS_NCOLS;BIOS_NROWS; - if(rul>rlr) return; if(cul>clr) return; if(rlr>=nrows) rlr=(Bit8u)nrows-1; if(clr>=ncols) clr=(Bit8u)ncols-1; - - // Get the current page + clr++; + /* Get the correct page */ if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + VGAMODES * curmode=GetCurrentMode(); + PhysPt base=PhysMake(curmode->sstart,curmode->slength*page); - /* Get this from active video mode */ - Bit16u textseg=0xb800; - PhysOff start=real_phys(textseg,ncols*nrows*2*page); + /* See how much lines need to be copies */ + Bit8u start,end;Bits next; + /* Copy some lines */ + if (nlines>0) { + start=rlr-nlines+1; + end=cul; + next=-1; + } else if (nlines<0) { + start=cul-nlines-1; + end=clr; + next=1; + } else { + nlines=rlr-rul+1; + goto filling; + } + do { + start+=next; + switch (curmode->memmodel) { + case MTEXT: + case CTEXT: + TEXT_CopyRow(curmode,cul,clr,start,start+nlines,base);break; + case PLANAR4: + PLANAR4_CopyRow(curmode,cul,clr,start,start+nlines,base);break; - Bit32u dcol=clr-cul+1; - Bit32u drow=rlr-rul+1; - - Bit32u tocopy; - PhysOff dest=start+((rlr*ncols)+cul)*2; - PhysOff src = 0;/* for gcc */ - if (nlines==0) { - nlines=(Bit8u)nrows; - } - if (nlines>=drow) { - tocopy=0; - } else { - tocopy=drow-nlines; - src=start+(((rul+tocopy-1)*ncols)+cul)*2; - } - - for (Bit32u y=0;y0) { + start=rul; + } else { + nlines-=nlines; + start=rlr-nlines; } + for (;nlines>0;nlines--) { + switch (curmode->memmodel) { + case MTEXT: + case CTEXT: + TEXT_FillRow(curmode,cul,clr,start,base,attr);break; + case PLANAR4: + PLANAR4_FillRow(curmode,cul,clr,start,base,attr);break; + } + start++; + } } -void INT10_ScrollUpWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page) { - -// Bit8u mode; - Bit16u fill=( (attr << 8) | ' '); - BIOS_NCOLS;BIOS_NROWS; - - if(rlr>nrows) rlr=(Bit8u)nrows; - if(clr>ncols) clr=(Bit8u)ncols; - - if(rul>rlr) return; - if(cul>clr) return; - - VGAMODES * curmode=GetCurrentMode(); - switch (curmode->memmodel) { - case CGA: - { - if (nlines==0) { - /* Clear Screen that we can */ - PhysOff dest=real_phys(0xb800,0); - for (Bit32u tel=0;tel<0x4000;tel++) { - mem_writew(dest,0x0000); - dest+=2; - } - return; - } - LOG_WARN("INT10:Scroll in CGA Mode"); - } - case MTEXT: - case CTEXT: - break; - default: - LOG_ERROR("INT10:Scroll on non supported graphics mode"); - } - - // Get the current page - if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - - /* Get this from active video mode */ - Bit16u textseg=0xb800; - PhysOff start=real_phys(textseg,ncols*nrows*2*page); - - Bit32u dcol=clr-cul+1; - Bit32u drow=rlr-rul+1; - - Bit32u tocopy; - PhysOff dest=start+((rul*ncols)+cul)*2; - PhysOff src; - if (nlines==0) { - nlines=(Bit8u)nrows; - } - - if (nlines>=drow) { - tocopy=0; - } else { - tocopy=drow-nlines; - src=start+(((rul+nlines)*ncols)+cul)*2; - } - for (Bit32u y=0;y7) return; - switch (curmode->memmodel) { - case MTEXT: - case CTEXT:{ - BIOS_NCOLS;BIOS_NROWS; - cur_col=CURSOR_POS_COL(page); - cur_row=CURSOR_POS_ROW(page); - vid_address=SCREEN_IO_START(ncols,nrows,page); - mem_address=SCREEN_MEM_START(ncols,nrows,page); - break; - } - case CGA:{ - vid_address=0; - mem_address=0; - break; - } - case PLANAR4:{ - mem_address=0; - vid_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page; - - break; - } - default: - vid_address=0; - mem_address=0; - break; - } - // Calculate the address knowing nbcols nbrows and page num + mem_address=page*curmode->slength; + /* Write the new page start */ real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address); + if (curmode->svgamode<8) mem_address>>=1; - // CRTC regs 0x0c and 0x0d + + /* Write the new start address in vgahardware */ IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(vid_address&0xff00)>>8); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(mem_address&0xff00)>>8); IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0d); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,vid_address&0x00ff); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,mem_address&0x00ff); // And change the BIOS page real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); @@ -265,14 +222,14 @@ INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u at break; case GRAPH: { - /* Split this up for certain graphics modes, since in PLANAR4 especially this is sooo slow */ /* Amount of lines */ Bit8u * fontdata; Bit16u x,y; switch (curmode->cheight) { case 8: // fontdata=&int10_font_08[chr*8]; - fontdata=Real2Host(RealGetVec(0x43))+chr*8; + if (chr<128) fontdata=Real2Host(RealGetVec(0x43))+chr*8; + else fontdata=Real2Host(RealGetVec(0x1F))+(chr-128)*8; break; case 14: fontdata=&int10_font_14[chr*14]; @@ -311,9 +268,15 @@ void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); + BIOS_NCOLS;BIOS_NROWS; while (count>0) { WriteChar(cur_col,cur_row,page,chr,attr,showattr); count--; + cur_col++; + if(cur_col==ncols) { + cur_col=0; + cur_row++; + } } } @@ -356,14 +319,14 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) { } // Do we need to scroll ? if(cur_row==nrows) { - INT10_ScrollUpWindow(0,0,nrows-1,ncols-1,1,0x07,page); + INT10_ScrollWindow(0,0,nrows-1,ncols-1,-1,0x07,page); cur_row--; } // Set the cursor for the page INT10_SetCursorPos(cur_row,cur_col,page); } -void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysOff string,Bit16u count,Bit8u page) { +void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) { if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; diff --git a/src/ints/int10_memory.cpp b/src/ints/int10_memory.cpp index 252dfd3..84b21e0 100644 --- a/src/ints/int10_memory.cpp +++ b/src/ints/int10_memory.cpp @@ -67,7 +67,8 @@ void INT10_SetupRomMemory(void) { for (i=0;i<0x10;i++) { real_writeb(0xC000,segoff++,static_functionality[i]); } - + MEM_BlockWrite(PhysMake(0xf000,0xfa6e),int10_font_08,128*8); + RealSetVec(0x1F,int10_romarea.font_8_second); }; diff --git a/src/ints/int10_misc.cpp b/src/ints/int10_misc.cpp index c2f256d..953b16b 100644 --- a/src/ints/int10_misc.cpp +++ b/src/ints/int10_misc.cpp @@ -23,7 +23,9 @@ +#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 */ @@ -68,15 +70,19 @@ struct Dynamic_Functionality { 7 reserved */ Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */ -}; +} +#if defined (_MSC_VER) +; #pragma pack() +#else +__attribute__ ((packed)); +#endif +void INT10_GetFuncStateInformation(PhysPt save) { -void INT10_GetFuncStateInformation(Bit16u seg,Bit16u off) { - - PhysOff save=Real2Phys(RealMake(seg,off)); + /* set static state pointer */ mem_writed(save,int10_romarea.static_state); /* Copy BIOS Segment areas */ diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index d2acd81..0419ba9 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -34,13 +34,14 @@ VGAMODES vga_modes[MODE_MAX+1]= {0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01}, {0x06, 0xFFFF, GRAPH, CGA, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01}, {0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00}, - {0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01}, - {0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01}, - {0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x0000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00}, - {0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x0000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02}, - {0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02}, - {0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02}, - {0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03} + + {0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x2000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01}, + {0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x4000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01}, + {0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00}, + {0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02}, + {0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02}, + {0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02}, + {0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0xFA00, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03} }; /* CRTC */ @@ -348,18 +349,18 @@ void INT10_SetVideoMode(Bit8u mode) { Bit32u tel; if(clearmem) { if(vga_modes[line].type==TEXT) { - PhysOff dest=real_phys(vga_modes[line].sstart,0); + PhysPt dest=PhysMake(vga_modes[line].sstart,0); for (tel=0;tel<0x4000;tel++) { mem_writew(dest,0x0720); dest+=2; } } else { - PhysOff dest=real_phys(0xb800,0); + PhysPt dest=PhysMake(0xb800,0); for (tel=0;tel<0x4000;tel++) { mem_writew(dest,0x0000); dest+=2; } - dest=real_phys(0xa000,0); + dest=PhysMake(0xa000,0); for (tel=0;tel<0x8000;tel++) { mem_writew(dest,0x0000); dest+=2; @@ -396,8 +397,5 @@ void INT10_SetVideoMode(Bit8u mode) { // Set active page 0 INT10_SetActivePage(0); /* Set some interrupt vectors */ - //TODO set 0x43 to the correct font height font RealSetVec(0x43,int10_romarea.font_8_first); - RealSetVec(0x1F,int10_romarea.font_8_second); - }; diff --git a/src/ints/int10_pal.cpp b/src/ints/int10_pal.cpp index fee1de1..c73553a 100644 --- a/src/ints/int10_pal.cpp +++ b/src/ints/int10_pal.cpp @@ -38,7 +38,7 @@ void INT10_SetOverscanBorderColor(Bit8u val) { IO_Write(VGAREG_ACTL_WRITE_DATA,val); } -void INT10_SetAllPaletteRegisters(PhysOff data) { +void INT10_SetAllPaletteRegisters(PhysPt data) { IO_Read(VGAREG_ACTL_RESET); // First the colors for(Bit8u i=0;i<0x10;i++) { @@ -80,7 +80,7 @@ void INT10_GetOverscanBorderColor(Bit8u * val) { *val=IO_Read(VGAREG_ACTL_READ_DATA); } -void INT10_GetAllPaletteRegisters(PhysOff data) { +void INT10_GetAllPaletteRegisters(PhysPt data) { IO_Read(VGAREG_ACTL_RESET); // First the colors for(Bit8u i=0;i<0x10;i++) { @@ -107,7 +107,7 @@ void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * bl *blue=IO_Read(VGAREG_DAC_DATA); } -void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data) { +void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data) { IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); for (;count>0;count--) { IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); @@ -116,7 +116,7 @@ void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data) { } } -void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysOff data) { +void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data) { IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); for (;count>0;count--) { mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index 5d6ce9f..74fd6fd 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -54,7 +54,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { //Perhaps also set mode 1 /* Calculate where the pixel is in video memory */ Bit16u base_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page; - PhysOff off=0xa0000+base_address+((y*curmode->swidth+x)>>3); + PhysPt off=0xa0000+base_address+((y*curmode->swidth+x)>>3); /* Bitmask and set/reset should do the rest */ mem_readb(off); mem_writeb(off,0xff); diff --git a/src/ints/mouse.cpp b/src/ints/mouse.cpp index baab599..23c95fe 100644 --- a/src/ints/mouse.cpp +++ b/src/ints/mouse.cpp @@ -150,7 +150,7 @@ static void mouse_reset(void) { mouse.max_y=199; mouse.range_x=639; mouse.range_y=199; - mouse.x=320; + mouse.x=0; // civ wont work otherwise mouse.y=100; mouse.events=0; mouse.mickey_x=0; @@ -196,6 +196,18 @@ static Bitu INT33_Handler(void) { mouse.times_pressed[but]=0; break; } + case 0x06: /* Return Button Release Data */ + { + Bit16u but=reg_bx; + reg_ax=mouse.buttons; + reg_cx=mouse.last_released_x[but]; + mouse.last_released_x[but]=0; + reg_dx=mouse.last_released_y[but]; + mouse.last_released_y[but]=0; + reg_bx=mouse.times_released[but]; + mouse.times_released[but]=0; + break; + } case 0x07: /* Define horizontal cursor range */ mouse.min_x=reg_cx; mouse.max_x=reg_dx; @@ -215,7 +227,7 @@ static Bitu INT33_Handler(void) { break; case 0x0c: /* Define interrupt subroutine parameters */ mouse.sub_mask=reg_cx; - mouse.sub_seg=Segs[es].value; + mouse.sub_seg=SegValue(es); mouse.sub_ofs=reg_dx; break; case 0x0f: /* Define mickey/pixel rate */ @@ -227,6 +239,19 @@ static Bitu INT33_Handler(void) { mouse.mickey_x=0; mouse.mickey_y=0; break; + case 0x14: /* Exchange event-handler */ + { Bit16u oldSeg = mouse.sub_seg; + Bit16u oldOfs = mouse.sub_ofs; + Bit16u oldMask= mouse.sub_mask; + // Set new values + mouse.sub_mask= reg_cx; + mouse.sub_seg = SegValue(es); + mouse.sub_ofs = reg_dx; + // Return old values + reg_cx = oldMask; + reg_dx = oldOfs; + SegSet16(es,oldSeg); + }; break; case 0x1c: /* Set interrupt rate */ /* Can't really set a rate this is host determined */ break; @@ -252,8 +277,11 @@ static Bitu INT74_Handler(void) { /* Check for an active Interrupt Handler that will get called */ if (mouse.sub_mask & mouse.event_queue[mouse.events].type) { /* Save lot's of registers */ - Bit16u oldax,oldbx,oldcx,olddx,oldsi,olddi; - oldax=reg_ax;oldbx=reg_bx;oldcx=reg_cx;olddx=reg_dx;oldsi=reg_si;olddi=reg_di; + Bit32u oldeax,oldebx,oldecx,oldedx,oldesi,oldedi,oldebp,oldesp; + Bit16u oldds,oldes,oldss; + oldeax=reg_eax;oldebx=reg_ebx;oldecx=reg_ecx;oldedx=reg_edx; + oldesi=reg_esi;oldedi=reg_edi;oldebp=reg_ebp;oldesp=reg_esp; + oldds=SegValue(ds); oldes=SegValue(es); oldss=SegValue(ss); // Save segments reg_ax=mouse.event_queue[mouse.events].type; reg_bx=mouse.event_queue[mouse.events].buttons; reg_cx=POS_X; @@ -265,7 +293,10 @@ static Bitu INT74_Handler(void) { mouse.mickey_y=0; } CALLBACK_RunRealFar(mouse.sub_seg,mouse.sub_ofs); - reg_ax=oldax;reg_bx=oldbx;reg_cx=oldcx;reg_dx=olddx;reg_si=oldsi;reg_di=olddi; + reg_eax=oldeax;reg_ebx=oldebx;reg_ecx=oldecx;reg_edx=oldedx; + reg_esi=oldesi;reg_edi=oldedi;reg_ebp=oldebp;reg_esp=oldesp; + SegSet16(ds,oldds); SegSet16(es,oldes); SegSet16(ss,oldss); // Save segments + } } IO_Write(0xa0,0x20); diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index d5f2c77..d08bd65 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include "dosbox.h" #include "callback.h" @@ -24,37 +25,50 @@ #include "dos_system.h" -#define XMS_VERSION 0x0300 /* version 3.00 */ -#define XMS_DRIVER_VERSION 0x0301 /* my driver version 3.01 */ +#define XMS_HANDLES 50 /* 50 XMS Memory Blocks */ +#define XMS_VERSION 0x0300 /* version 3.00 */ +#define XMS_DRIVER_VERSION 0x0301 /* my driver version 3.01 */ -#define XMS_GET_VERSION 0x00 -#define XMS_ALLOCATE_HIGH_MEMORY 0x01 -#define XMS_FREE_HIGH_MEMORY 0x02 -#define XMS_GLOBAL_ENABLE_A20 0x03 -#define XMS_GLOBAL_DISABLE_A20 0x04 -#define XMS_LOCAL_ENABLE_A20 0x05 -#define XMS_LOCAL_DISABLE_A20 0x06 -#define XMS_QUERY_A20 0x07 -#define XMS_QUERY_FREE_EXTENDED_MEMORY 0x08 -#define XMS_ALLOCATE_EXTENDED_MEMORY 0x09 -#define XMS_FREE_EXTENDED_MEMORY 0x0a -#define XMS_MOVE_EXTENDED_MEMORY_BLOCK 0x0b -#define XMS_LOCK_EXTENDED_MEMORY_BLOCK 0x0c -#define XMS_UNLOCK_EXTENDED_MEMORY_BLOCK 0x0d -#define XMS_GET_EMB_HANDLE_INFORMATION 0x0e -#define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f -#define XMS_ALLOCATE_UMB 0x10 -#define XMS_DEALLOCATE_UMB 0x11 +#define XMS_GET_VERSION 0x00 +#define XMS_ALLOCATE_HIGH_MEMORY 0x01 +#define XMS_FREE_HIGH_MEMORY 0x02 +#define XMS_GLOBAL_ENABLE_A20 0x03 +#define XMS_GLOBAL_DISABLE_A20 0x04 +#define XMS_LOCAL_ENABLE_A20 0x05 +#define XMS_LOCAL_DISABLE_A20 0x06 +#define XMS_QUERY_A20 0x07 +#define XMS_QUERY_FREE_EXTENDED_MEMORY 0x08 +#define XMS_ALLOCATE_EXTENDED_MEMORY 0x09 +#define XMS_FREE_EXTENDED_MEMORY 0x0a +#define XMS_MOVE_EXTENDED_MEMORY_BLOCK 0x0b +#define XMS_LOCK_EXTENDED_MEMORY_BLOCK 0x0c +#define XMS_UNLOCK_EXTENDED_MEMORY_BLOCK 0x0d +#define XMS_GET_EMB_HANDLE_INFORMATION 0x0e +#define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f +#define XMS_ALLOCATE_UMB 0x10 +#define XMS_DEALLOCATE_UMB 0x11 -#define HIGH_MEMORY_IN_USE 0x92 -#define HIGH_MEMORY_NOT_ALLOCATED 0x93 -#define XMS_OUT_OF_SPACE 0xa0 -#define XMS_INVALID_HANDLE 0xa2 +#define HIGH_MEMORY_IN_USE 0x92 +#define HIGH_MEMORY_NOT_ALLOCATED 0x93 +#define XMS_OUT_OF_SPACE 0xa0 +#define XMS_OUT_OF_HANDLES 0xa1 +#define XMS_INVALID_HANDLE 0xa2 +struct XMS_Block { + Bit16u prev,next; + Bit16u size; /* Size in kb's */ + PhysPt phys; + Bit8u locked; + void * data; + bool active; +}; static Bit16u call_xms; static RealPt xms_callback; +static XMS_Block xms_handles[XMS_HANDLES]; + + static bool multiplex_xms(void) { switch (reg_ax) { @@ -62,7 +76,7 @@ static bool multiplex_xms(void) { reg_al=0x80; return true; case 0x4310: /* XMS handler seg:offset */ - SetSegment_16(es,RealSeg(xms_callback)); + SegSet16(es,RealSeg(xms_callback)); reg_bx=RealOff(xms_callback); return true; } @@ -70,51 +84,29 @@ static bool multiplex_xms(void) { }; -#if defined (_MSC_VER) -#pragma pack(1) -#endif +#pragma pack (push,1) struct XMS_MemMove{ Bit32u length; Bit16u src_handle; - RealPt src_offset; + union { + RealPt realpt; + Bit32u offset; + } src; Bit16u dest_handle; - RealPt dest_offset; -} -#if defined (_MSC_VER) -; -#pragma pack() -#else -__attribute__ ((packed)); -#endif - -static void XMS_MoveBlock(PhysOff block,Bit8u * result) { - XMS_MemMove moveblock; -//TODO Will not work on other endian, probably base it on a class would be nice - MEM_BlockRead(block,(Bit8u *)&moveblock,sizeof(XMS_MemMove)); - HostOff src; - PhysOff dest; - if (moveblock.src_handle) { - src=memory+EMM_Handles[moveblock.src_handle].phys_base+moveblock.src_offset; - } else { - src=Real2Host(moveblock.src_offset); - } - if (moveblock.dest_handle) { - dest=EMM_Handles[moveblock.dest_handle].phys_base+moveblock.dest_offset; - } else { - dest=Real2Phys(moveblock.dest_offset); - } - //memcpy((void *)dest,(void *)src,moveblock.length); - MEM_BlockWrite(dest,src,moveblock.length); - *result=0; -}; + union { + RealPt realpt; + Bit32u offset; + } dest; +} GCC_ATTRIBUTE(packed); +#pragma pack (pop) Bitu XMS_Handler(void) { switch (reg_ah) { case XMS_GET_VERSION: /* 00 */ reg_ax=XMS_VERSION; reg_bx=XMS_DRIVER_VERSION; - reg_dx=0; //TODO HMA Maybe + reg_dx=0; /* No we don't have HMA */ break; case XMS_ALLOCATE_HIGH_MEMORY: /* 01 */ case XMS_FREE_HIGH_MEMORY: /* 02 */ @@ -125,42 +117,198 @@ Bitu XMS_Handler(void) { case XMS_QUERY_A20: /* 07 */ LOG_WARN("XMS:Unhandled call %2X",reg_ah);break; case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */ - EMM_GetFree(®_ax,®_dx); - reg_ax<<=2;reg_dx<<=2; - reg_bl=0; - break; - case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */ - EMM_Allocate(PAGES(reg_dx*1024),®_dx); - if (reg_dx) reg_ax=1; - else { reg_ax=0;reg_bl=0xb0; } - break; - case XMS_FREE_EXTENDED_MEMORY: /* 0a */ - EMM_Free(reg_dx); - reg_ax=1; - break; - - case XMS_MOVE_EXTENDED_MEMORY_BLOCK: /* 0b */ - XMS_MoveBlock(real_phys(Segs[ds].value,reg_si),®_bl); - if (reg_bl) reg_ax=0; - else reg_ax=1; - break; - case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* 0c */ - if ((!EMM_Handles[reg_dx].active) || (EMM_Handles[reg_dx].free)) { - reg_ax=0; - reg_bl=0xa2; /* Invalid block */ + /* Scan the tree for free memory and find largest free block */ + { + Bit16u index=1;reg_ax=0;reg_dx=0; + while (xms_handles[index].active) { + if (!xms_handles[index].data) { + if(xms_handles[index].size>reg_ax) reg_ax=xms_handles[index].size; + reg_dx+=xms_handles[index].size; + } + if (xms_handles[index].next> 16) & 0xffff); + case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */ + { + Bit16u index=1; + /* First make reg_dx a multiple of PAGE_KB */ + if (reg_dx & (PAGE_KB-1)) reg_dx=(reg_dx&(~(PAGE_KB-1)))+PAGE_KB; + while (xms_handles[index].active) { + /* Find a free block, check if there's enough size */ + if (!xms_handles[index].data && xms_handles[index].size>=reg_dx) { + /* Check if block is bigger than request */ + if (xms_handles[index].size>reg_dx) { + /* Split Block, find new handle and split up memory */ + Bit16u new_index=1; + while (new_index=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { + reg_ax=0; + reg_bl=XMS_INVALID_HANDLE; + return CBRET_NONE; + } + /* Remove the mapping to the memory */ + MEM_ClearMapping(PAGE_COUNT(xms_handles[reg_dx].phys),PAGE_COUNT(xms_handles[reg_dx].size*1024)); + /* Free the memory in the block and merge the blocks previous and next block */ + Bit16u prev=xms_handles[reg_dx].prev; + Bit16u next=xms_handles[reg_dx].next; + free(xms_handles[reg_dx].data); + xms_handles[reg_dx].data=0; + if ((next=XMS_HANDLES) || !xms_handles[block.src_handle].active ||!xms_handles[block.src_handle].data) { + reg_ax=0; + reg_bl=0xa3; /* Src Handle invalid */ + return CBRET_NONE; + } + if (block.src.offset>=(xms_handles[block.src_handle].size*1024U)) { + reg_ax=0; + reg_bl=0xa4; /* Src Offset invalid */ + return CBRET_NONE; + } + if (block.length>xms_handles[block.src_handle].size*1024U-block.src.offset) { + reg_ax=0; + reg_bl=0xa7; /* Length invalid */ + return CBRET_NONE; + + } + src=xms_handles[block.src_handle].phys+block.src.offset; + } else { + src=Real2Phys(block.src.realpt); + } + if (block.dest_handle) { + if ((block.dest_handle>=XMS_HANDLES) || !xms_handles[block.dest_handle].active ||!xms_handles[block.dest_handle].data) { + reg_ax=0; + reg_bl=0xa3; /* Dest Handle invalid */ + return CBRET_NONE; + } + if (block.dest.offset>=(xms_handles[block.dest_handle].size*1024U)) { + reg_ax=0; + reg_bl=0xa4; /* Dest Offset invalid */ + return CBRET_NONE; + } + if (block.length>xms_handles[block.dest_handle].size*1024U-block.dest.offset) { + reg_ax=0; + reg_bl=0xa7; /* Length invalid */ + return CBRET_NONE; + } + dest=xms_handles[block.dest_handle].phys+block.dest.offset; + } else { + dest=Real2Phys(block.dest.realpt); + } + MEM_BlockCopy(dest,src,block.length); + reg_ax=1;reg_bl=0; + } + break; + case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* 0c */ + { + /* Check for a valid handle */ + if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { + reg_ax=0; + reg_bl=XMS_INVALID_HANDLE; + return CBRET_NONE; + } + if (xms_handles[reg_dx].locked<255) xms_handles[reg_dx].locked++; + reg_bx=(Bit16u)(xms_handles[reg_dx].phys & 0xFFFF); + reg_dx=(Bit16u)(xms_handles[reg_dx].phys>>16); + reg_ax=1; + break; + } case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */ - reg_ax=1; + /* Check for a valid handle */ + if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { + reg_ax=0; + reg_bl=XMS_INVALID_HANDLE; + return CBRET_NONE; + } + if (xms_handles[reg_dx].locked) xms_handles[reg_dx].locked--; + reg_ax=1;reg_bl=0; break; case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */ - LOG_WARN("XMS:Unhandled call %2X",reg_ah);break; + /* Check for a valid handle */ + if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { + reg_ax=0; + reg_bl=XMS_INVALID_HANDLE; + return CBRET_NONE; + } + reg_bh=xms_handles[reg_dx].locked; + /* Find available blocks */ + reg_bx=0;{ for (Bitu i=0;ipsp_seg=dos.psp; - MEM_BlockRead(real_phys(dos.psp,0),&info->psp_copy,sizeof(PSP)); + MEM_BlockRead(PhysMake(dos.psp,0),&info->psp_copy,sizeof(PSP)); /* Get the file name cmd_line 0 */ - PhysOff envblock=real_phys(info->psp_copy.environment,0); + PhysPt envblock=PhysMake(info->psp_copy.environment,0); do {} while (mem_readw(envblock++)); envblock+=3; MEM_StrCopy(envblock,info->full_name,32); @@ -107,7 +107,7 @@ char * Program::GetEnvStr(char * env_str) { /* 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 *)real_host(prog_info->psp_copy.environment,0); + 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]=='=') { @@ -119,7 +119,7 @@ char * Program::GetEnvStr(char * env_str) { }; char * Program::GetEnvNum(Bit32u num) { - char * envstart=(char *)real_host(prog_info->psp_copy.environment,0); + char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0); while (*envstart) { if (!num) return envstart; envstart+=strlen(envstart)+1; @@ -129,7 +129,7 @@ char * Program::GetEnvNum(Bit32u num) { } Bit32u Program::GetEnvCount(void) { - char * envstart=(char *)real_host(prog_info->psp_copy.environment,0); + char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0); Bit32u num=0; while (*envstart) { envstart+=strlen(envstart)+1; @@ -139,13 +139,13 @@ Bit32u Program::GetEnvCount(void) { } bool Program::SetEnv(char * env_entry,char * new_string) { - MCB * env_mcb=(MCB *)real_host(prog_info->psp_copy.environment-1,0); + 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 *)real_host(prog_info->psp_copy.environment,0); + 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 */ diff --git a/src/misc/support.cpp b/src/misc/support.cpp index 1348dc7..4295951 100644 --- a/src/misc/support.cpp +++ b/src/misc/support.cpp @@ -26,7 +26,7 @@ #include #include "dosbox.h" #include "support.h" - +#include "video.h" /* Ripped some source from freedos for this one. @@ -82,38 +82,49 @@ char *trim(char *str) { return ltrim(str); } -bool wildcmp(char *wild, char *string) { - char *cp, *mp; - while ((*string) && (*wild != '*')) { - if ((*wild != *string) && (*wild != '?')) { - return false; - } - wild++; - string++; - } - - while (*string) { - if (*wild == '*') { - if (!*++wild) { - return true; +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++; } - mp = wild; - cp = string+1; - } else if ((*wild == *string) || (*wild == '?')) { + 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++; - } else { - wild = mp; - string = cp++; } } - - while (*wild == '*') { - wild++; - } - return !*wild; -} + return ((*string==0) && (*wild==0)); +}; bool ScanCMDBool(char * cmd,char * check) { char * scan=cmd;size_t c_len=strlen(check); @@ -197,7 +208,7 @@ void S_Warn(char * format,...) { va_start(msg,format); vsprintf(buf,format,msg); va_end(msg); -#ifdef C_DEBUG +#if C_DEBUG DEBUG_ShowMsg(buf); #else GFX_ShowMsg(buf); @@ -219,6 +230,7 @@ void E_Exit(char * format,...) { printf(buf); printf("Press ENTER to stop\n"); fgetc(stdin); - exit(2); + GFX_Stop(); + exit(2); }; \ No newline at end of file diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index 9ad95e1..114b25b 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,5 +1,6 @@ #define INLINE __forceinline -#define VERSION "0.50" +#define VERSION "0.55" + +#define GCC_ATTRIBUTE(x) /* attribute not supported */ -/* Euhm */ diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 63e4dad..2020d9b 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -19,6 +19,7 @@ #include #include + #include "shell_inc.h" Bitu call_shellstop; @@ -139,13 +140,16 @@ void SHELL_Init() { /* Now call up the shell for the first time */ Bit16u psp_seg=DOS_GetMemory(16); Bit16u env_seg=DOS_GetMemory(1+(4096/16)); + 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 *)real_host(env_seg,0); + MCB * env_mcb=(MCB *)HostMake(env_seg,0); env_mcb->psp_segment=psp_seg; env_mcb->size=4096/16; real_writed(env_seg+1,0,0); - PSP * psp=(PSP *)real_host(psp_seg,0); + 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"); @@ -158,15 +162,16 @@ void SHELL_Init() { 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); /* Setup internal DOS Variables */ dos.dta=RealMake(psp_seg,0x80); dos.psp=psp_seg; PROGRAM_Info info; strcpy(info.full_name,"Z:\\COMMAND.COM"); info.psp_seg=psp_seg; - MEM_BlockRead(real_phys(dos.psp,0),&info.psp_copy,sizeof(PSP)); + MEM_BlockRead(PhysMake(dos.psp,0),&info.psp_copy,sizeof(PSP)); char line[256]; strcpy(line,"/INIT Z:\\AUTOEXEC.BAT"); info.cmd_line=line; diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index c34624b..1dcec3b 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -53,6 +53,7 @@ void DOS_Shell::DoCommand(char * line) { while (*line) { if (*line==32) break; if (*line=='/') break; + if ((*line=='.') && (*(line+1)=='.')) break; *cmd_write++=*line++; } *cmd_write=0; @@ -113,7 +114,7 @@ void DOS_Shell::CMD_EXIT(char * args) { void DOS_Shell::CMD_CHDIR(char * args) { if (!*args) { Bit8u drive=DOS_GetDefaultDrive()+'A'; - Bit8u dir[DOS_PATHLENGTH]; + char dir[DOS_PATHLENGTH]; DOS_GetCurrentDir(0,dir); WriteOut("%c:\\%s\n",drive,dir); } @@ -185,7 +186,7 @@ void DOS_Shell::CMD_DIR(char * args) { if (strlen(args)==0) args="*.*"; /* Make a full path in the args */ - if (!DOS_Canonicalize(args,(Bit8u*)path)) { + if (!DOS_Canonicalize(args,path)) { WriteOut(MSG_Get("SHELL_CMD_DIR_PATH_ERROR")); return; } diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 1d003c3..df465b1 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -24,7 +24,7 @@ void DOS_Shell::ShowPrompt(void) { Bit8u drive=DOS_GetDefaultDrive()+'A'; - Bit8u dir[DOS_PATHLENGTH]; + char dir[DOS_PATHLENGTH]; DOS_GetCurrentDir(0,dir); WriteOut("%c:\\%s>",drive,dir); } @@ -138,36 +138,46 @@ void DOS_Shell::Execute(char * name,char * args) { /* Check for a full name */ fullname=Which(name); if (!fullname) { - WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND")); + WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),name); return; } if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) { /* Run the .bat file */ bf=new BatchFile(this,fullname,args); } else { - /* Run the .exe or .com file */ - ParamBlock block; + /* 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); + //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); - MEM_BlockWrite(real_phys(prog_info->psp_seg,128),&cmd,128); - block.exec.cmdtail=RealMake(prog_info->psp_seg,128); - block.exec.envseg=0; - block.exec.fcb1=0; - block.exec.fcb2=0; + block.InitExec(RealMake(prog_info->psp_seg,128)); /* Save CS:IP to some point where i can return them from */ RealPt newcsip; newcsip=CALLBACK_RealPointer(call_shellstop); - SetSegment_16(cs,RealSeg(newcsip)); + SegSet16(cs,RealSeg(newcsip)); reg_ip=RealOff(newcsip); - - DOS_Execute(fullname,&block,0); - DOSBOX_RunMachine(); - Bit16u blah=0; + /* Start up a dos execute interrupt */ + reg_ax=0x4b00; + //Filename pointer + SegSet16(ds,SegValue(ss)); + reg_dx=RealOff(file_name); + //Paramblock + SegSet16(es,SegValue(ss)); + reg_bx=reg_sp; + flags.intf=false; + CALLBACK_RunRealInt(0x21); + reg_sp+=0x200; } diff --git a/visualc/dosbox.dsp b/visualc/dosbox.dsp index f7a513b..b963277 100644 --- a/visualc/dosbox.dsp +++ b/visualc/dosbox.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MD /W3 /GX /O1 /Op /Ob2 /I "../include" /I "../src/platform/visualc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FAs /FD /QxMi /bQipo /c +# ADD CPP /nologo /G6 /MD /W3 /GX /O1 /Op /Ob2 /I "../include" /I "../src/platform/visualc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FAs /FR /FD /QxMi /bQipo /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -507,7 +507,11 @@ SOURCE=..\src\fpu\fpu.cpp # End Source File # Begin Source File -SOURCE=..\src\fpu\fpu_load.h +SOURCE=..\src\fpu\fpu_instructions.h +# End Source File +# Begin Source File + +SOURCE=..\src\fpu\fpu_types.h # End Source File # End Group # Begin Group "visualc" @@ -576,6 +580,10 @@ SOURCE=..\include\dosbox.h # End Source File # Begin Source File +SOURCE=..\include\fpu.h +# End Source File +# Begin Source File + SOURCE=..\include\hardware.h # End Source File # Begin Source File @@ -631,9 +639,5 @@ SOURCE=..\include\support.h SOURCE=..\include\timer.h # End Source File # End Group -# Begin Source File - -SOURCE=.\shit.txt -# End Source File # End Target # End Project