diff --git a/include/setup.h b/include/setup.h index 1024d547..fa7bdec0 100644 --- a/include/setup.h +++ b/include/setup.h @@ -16,13 +16,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: setup.h,v 1.31 2008-01-27 18:31:01 qbix79 Exp $ */ +/* $Id: setup.h,v 1.32 2008-02-10 11:14:02 qbix79 Exp $ */ #ifndef DOSBOX_SETUP_H #define DOSBOX_SETUP_H #ifdef _MSC_VER #pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4290 ) #endif #ifndef DOSBOX_CROSS_H @@ -47,7 +48,6 @@ #include #endif -#pragma warning(disable: 4290) class Hex { private: @@ -56,30 +56,39 @@ public: Hex(int in):_hex(in) { }; Hex():_hex(0) { }; bool operator==(Hex const& other) {return _hex == other._hex;} + operator int () const { return _hex; } + }; class Value { -public: //for the time being. Added a n to _hex to keep compilable during the work - Hex _hexn; - int _hex; +/* + * Multitype storage container that is aware of the currently stored type in it. + * Value st = "hello"; + * Value in = 1; + * st = 12 //Exception + * in = 12 //works + */ +private: + Hex _hex; bool _bool; int _int; std::string* _string; double _double; public: class WrongType { }; // Conversion error class - enum { V_NONE, V_HEX, V_BOOL, V_INT, V_STRING, V_DOUBLE} type; + enum Etype { V_NONE, V_HEX, V_BOOL, V_INT, V_STRING, V_DOUBLE,V_CURRENT} type; /* Constructors */ - Value() :type(V_NONE) { }; - Value(Hex in) :type(V_HEX), _hexn(in) { }; + Value() :type(V_NONE),_string(0) { }; + Value(Hex in) :type(V_HEX), _hex(in) { }; Value(int in) :type(V_INT), _int(in) { }; Value(bool in) :type(V_BOOL), _bool(in) { }; Value(double in) :type(V_DOUBLE), _double(in) { }; Value(std::string const& in) :type(V_STRING), _string(new std::string(in)) { }; Value(char const * const in) :type(V_STRING), _string(new std::string(in)) { }; - Value(Value const& in) {plaincopy(in);} + Value(Value const& in):_string(0) {plaincopy(in);} ~Value() { destroy();}; + Value(std::string const& in,Etype _t) :type(V_NONE),_string(0){SetValue(in,_t);} /* Assigment operators */ Value& operator= (Hex in) throw(WrongType) { return copy(Value(in));} @@ -96,91 +105,108 @@ public: operator int () const throw(WrongType); operator double () const throw(WrongType); operator char const* () const throw(WrongType); + void SetValue(std::string const& in,Etype _type = V_CURRENT) throw(WrongType); + std::string ToString() const; private: - void destroy(); + void destroy() throw(); Value& copy(Value const& in) throw(WrongType); - void plaincopy(Value const& in); - + void plaincopy(Value const& in) throw(); + void set_hex(std::string const& in); + void set_int(std::string const&in); + void set_bool(std::string const& in); + void set_string(std::string const& in); + void set_double(std::string const& in); }; class Property { public: - struct Changable { enum Value {Always, WhenIdle,OnlyAtStart};}; - Property(char const * const _propname):propname(_propname) { } - virtual void SetValue(char* input)=0; - virtual void GetValuestring(char* str) const=0; + struct Changeable { enum Value {Always, WhenIdle,OnlyAtStart};}; + const std::string propname; + + Property(std::string const& _propname, Changeable::Value when):propname(_propname),change(when) { } + void Set_values(const char * const * in); + void Set_help(std::string const& str); + char const* Get_help(); + virtual void SetValue(std::string const& str)=0; Value const& GetValue() const { return value;} - virtual ~Property(){ } - std::string propname; - //CheckValue returns true (and sets value to in) if value is in suggested_values; + //CheckValue returns true if value is in suggested_values; //Type specific properties are encouraged to override this and check for type //specific features. virtual bool CheckValue(Value const& in, bool warn); //Set interval value to in or default if in is invalid. force always sets the value. - void SetVal(Value const& in, bool forced) {if(forced || CheckValue(in,false)) value = in; else value = default_value;} + void SetVal(Value const& in, bool forced,bool warn=true) {if(forced || CheckValue(in,warn)) value = in; else value = default_value;} + virtual ~Property(){ } protected: Value value; std::vector suggested_values; typedef std::vector::iterator iter; Value default_value; - /*const*/ Changable::Value change; + const Changeable::Value change; }; class Prop_int:public Property { public: - Prop_int(char const * const _propname, int _value):Property(_propname) { + Prop_int(std::string const& _propname,Changeable::Value when, int _value) + :Property(_propname,when) { default_value = value = _value; min = max = -1; } + Prop_int(std::string const& _propname,Changeable::Value when, int _min,int _max,int _value) + :Property(_propname,when) { + default_value = value = _value; + min = _min; + max = _max; + } void SetMinMax(Value const& min,Value const& max) {this->min = min; this->max=max;} - void SetValue(char* input); - void GetValuestring(char* str) const; + void SetValue(std::string const& in); ~Prop_int(){ } virtual bool CheckValue(Value const& in, bool warn); private: Value min,max; }; + class Prop_double:public Property { public: - Prop_double(char const * const _propname, double _value):Property(_propname){ + Prop_double(std::string const & _propname, Changeable::Value when, double _value) + :Property(_propname,when){ default_value = value = _value; } - void SetValue(char* input); - void GetValuestring(char* str) const; + void SetValue(std::string const& input); ~Prop_double(){ } }; class Prop_bool:public Property { public: - Prop_bool(char const * const _propname, bool _value):Property(_propname) { + Prop_bool(std::string const& _propname, Changeable::Value when, bool _value) + :Property(_propname,when) { default_value = value = _value; } - void SetValue(char* input); - void GetValuestring(char* str) const; + void SetValue(std::string const& in); ~Prop_bool(){ } }; class Prop_string:public Property{ public: - Prop_string(char const * const _propname, char const * const _value):Property(_propname) { + Prop_string(std::string const& _propname, Changeable::Value when, char const * const _value) + :Property(_propname,when) { default_value = value = _value; } - void SetValue(char* input); - void GetValuestring(char* str) const; + void SetValue(std::string const& in); ~Prop_string(){ } - }; + class Prop_hex:public Property { public: - Prop_hex(char const * const _propname, int _value):Property(_propname) { - default_value = value._hex = _value; + Prop_hex(std::string const& _propname, Changeable::Value when, Hex _value) + :Property(_propname,when) { + default_value = value = _value; } - void SetValue(char* input); + void SetValue(std::string const& in); ~Prop_hex(){ } - void GetValuestring(char* str) const; }; +#define NO_SUCH_PROPERTY "PROP_NOT_EXIST" class Section { private: typedef void (*SectionFunction)(Section*); @@ -198,7 +224,7 @@ private: std::list destroyfunctions; std::string sectionname; public: - Section(char const * const _sectionname):sectionname(_sectionname) { } + Section(std::string const& _sectionname):sectionname(_sectionname) { } void AddInitFunction(SectionFunction func,bool canchange=false); void AddDestroyFunction(SectionFunction func,bool canchange=false); @@ -206,46 +232,61 @@ public: void ExecuteDestroy(bool destroyall=true); const char* GetName() const {return sectionname.c_str();} - virtual char const * GetPropValue(char const * const _property) const =0; - virtual void HandleInputline(char * _line)=0; + virtual std::string GetPropValue(std::string const& _property) const =0; + virtual void HandleInputline(std::string const& _line)=0; virtual void PrintData(FILE* outfile) const =0; virtual ~Section() { /*Children must call executedestroy ! */} }; - +class Prop_multival; class Section_prop:public Section { private: std::list properties; typedef std::list::iterator it; typedef std::list::const_iterator const_it; + public: - Section_prop(char const * const _sectionname):Section(_sectionname){} - Prop_int& Add_int(char const * const _propname, int _value=0); - Prop_string& Add_string(char const * const _propname, char const * const _value=NULL); - Prop_bool& Add_bool(char const * const _propname, bool _value=false); - Prop_hex& Add_hex(char const * const _propname, int _value=0); - void Add_double(char const * const _propname, double _value=0.0); + Section_prop(std::string const& _sectionname):Section(_sectionname){} + Prop_int* Add_int(std::string const& _propname, Property::Changeable::Value when, int _value=0); + Prop_string* Add_string(std::string const& _propname, Property::Changeable::Value when, char const * const _value=NULL); + Prop_bool* Add_bool(std::string const& _propname, Property::Changeable::Value when, bool _value=false); + Prop_hex* Add_hex(std::string const& _propname, Property::Changeable::Value when, Hex _value=0); +// void Add_double(char const * const _propname, double _value=0.0); P + Prop_multival *Add_multi(std::string const& _propname, Property::Changeable::Value when,std::string const& sep); Property* Get_prop(int index); - int Get_int(char const * const _propname) const; - const char* Get_string(char const * const _propname) const; - bool Get_bool(char const * const _propname) const; - int Get_hex(char const * const _propname) const; - double Get_double(char const * const _propname) const; - void HandleInputline(char *gegevens); + int Get_int(std::string const& _propname) const; + const char* Get_string(std::string const& _propname) const; + bool Get_bool(std::string const& _propname) const; + Hex Get_hex(std::string const& _propname) const; + double Get_double(std::string const& _propname) const; + Prop_multival* Get_multival(std::string const& _propname) const; + void HandleInputline(std::string const& gegevens); void PrintData(FILE* outfile) const; - virtual char const * GetPropValue(char const * const _property) const; + virtual std::string GetPropValue(std::string const& _property) const; //ExecuteDestroy should be here else the destroy functions use destroyed properties virtual ~Section_prop(); }; +class Prop_multival:public Property{ + Section_prop* section; + std::string seperator; +public: + Prop_multival(std::string const& _propname, Changeable::Value when,std::string const& sep):Property(_propname,when), section(new Section_prop("")),seperator(sep) { + value = ""; + } + Section_prop *GetSection() { return section; } + const Section_prop *GetSection() const { return section; } + void SetValue(std::string const& input); +}; //value bevat totalle string. setvalue zet elk van de sub properties en checked die. + class Section_line: public Section{ public: - Section_line(char const * const _sectionname):Section(_sectionname){} + Section_line(std::string const& _sectionname):Section(_sectionname){} ~Section_line(){ExecuteDestroy(true);} - void HandleInputline(char* gegevens); + void HandleInputline(std::string const& gegevens); void PrintData(FILE* outfile) const; - virtual const char* GetPropValue(char const * const _property) const; + virtual std::string GetPropValue(std::string const& _property) const; std::string data; }; @@ -267,7 +308,7 @@ public: Section_prop * AddSection_prop(char const * const _name,void (*_initfunction)(Section*),bool canchange=false); Section* GetSection(int index); - Section* GetSection(char const* const _sectionname) const; + Section* GetSection(std::string const&_sectionname) const; Section* GetSectionFromProperty(char const * const prop) const; void SetStartUp(void (*_function)(void)); diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index cb452b91..e0ff121a 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.cpp,v 1.107 2008-01-16 20:17:15 c2woody Exp $ */ +/* $Id: cpu.cpp,v 1.108 2008-02-10 11:14:03 qbix79 Exp $ */ #include #include @@ -2164,16 +2164,16 @@ public: CPU_Cycles=0; CPU_SkipCycleAutoAdjust=false; - std::string str; - CommandLine cmd(0,section->Get_string("cycles")); - cmd.FindCommand(1,str); - - if (str=="max") { + Prop_multival* p = section->Get_multival("cycles"); + std::string type = p->GetSection()->Get_string("type"); + std::string str ; + CommandLine cmd(0,p->GetSection()->Get_string("parameters")); + if (type=="max") { CPU_CycleMax=0; CPU_CyclePercUsed=100; CPU_CycleAutoAdjust=true; CPU_CycleLimit=-1; - for (Bitu cmdnum=2; cmdnum<=cmd.GetCount(); cmdnum++) { + for (Bitu cmdnum=1; cmdnum<=cmd.GetCount(); cmdnum++) { if (cmd.FindCommand(cmdnum,str)) { if (str.find('%')==str.length()-1) { str.erase(str.find('%')); @@ -2193,12 +2193,12 @@ public: } } } else { - if (str=="auto") { + if (type=="auto") { CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CYCLES; CPU_CycleMax=3000; CPU_OldCycleMax=3000; CPU_CyclePercUsed=100; - for (Bitu cmdnum=2; cmdnum<=cmd.GetCount(); cmdnum++) { + for (Bitu cmdnum=0; cmdnum<=cmd.GetCount(); cmdnum++) { if (cmd.FindCommand(cmdnum,str)) { if (str.find('%')==str.length()-1) { str.erase(str.find('%')); @@ -2225,7 +2225,8 @@ public: } } } - } else { + } else if(type =="fixed") { + cmd.FindCommand(1,str); int rmdval=0; std::istringstream stream(str); stream >> rmdval; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 9e09b4df..957ba59d 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dosbox.cpp,v 1.127 2008-02-03 20:43:13 c2woody Exp $ */ +/* $Id: dosbox.cpp,v 1.128 2008-02-10 11:14:03 qbix79 Exp $ */ #include #include @@ -270,57 +270,66 @@ static void DOSBOX_RealInit(Section * sec) { "# They are used to (briefly) document the effect of each option.\n"); MAPPER_AddHandler(DOSBOX_UnlockSpeed, MK_f12, MMOD2,"speedlock","Speedlock"); - svgaCard=SVGA_None; - machine=MCH_VGA; - int10.vesa_nolfb=false; std::string cmd_machine; - const char * mtype; - if (control->cmdline->FindString("-machine",cmd_machine,true)) mtype=cmd_machine.c_str(); - else mtype=section->Get_string("machine"); - if (strcasecmp(mtype,"cga")==0) machine=MCH_CGA; - else if (strcasecmp(mtype,"tandy")==0) machine=MCH_TANDY; - else if (strcasecmp(mtype,"pcjr")==0) machine=MCH_PCJR; - else if (strcasecmp(mtype,"hercules")==0) machine=MCH_HERC; - else if (strcasecmp(mtype,"ega")==0) machine=MCH_EGA; - else if ((strcasecmp(mtype,"vga")==0) || (strcasecmp(mtype,"vga_s3")==0) || - (strcasecmp(mtype,"svga")==0) || (strcasecmp(mtype,"svga_s3")==0)) { - machine=MCH_VGA; - svgaCard=SVGA_S3Trio; - } else if (strcasecmp(mtype,"vesa_nolfb")==0) { - machine=MCH_VGA; - svgaCard=SVGA_S3Trio; - int10.vesa_nolfb=true; - } else if ((strcasecmp(mtype,"vga_et4000")==0) || (strcasecmp(mtype,"svga_et4000")==0)) { - machine=MCH_VGA; - svgaCard=SVGA_TsengET4K; - } else if ((strcasecmp(mtype,"vga_et3000")==0) || (strcasecmp(mtype,"svga_et3000")==0)) { - machine=MCH_VGA; - svgaCard=SVGA_TsengET3K; - } else if ((strcasecmp(mtype,"vga_pvga1a")==0) || (strcasecmp(mtype,"svga_pvga1a")==0) || - (strcasecmp(mtype,"svga_paradise")==0)) { - machine=MCH_VGA; - svgaCard=SVGA_ParadisePVGA1A; - } else if (strcasecmp(mtype,"vgaonly")==0) { - machine=MCH_VGA; - svgaCard=SVGA_None; - } else { - LOG_MSG("DOSBOX:Unknown machine type %s",mtype); + if (control->cmdline->FindString("-machine",cmd_machine,true)){ + //update value in config (else no matching against suggested values + section->HandleInputline(std::string("machine=") + cmd_machine); } + + std::string mtype(section->Get_string("machine")); + svgaCard = SVGA_S3Trio; + machine = MCH_VGA; + int10.vesa_nolfb = false; + if (mtype == "cga") { machine = MCH_CGA; } + else if (mtype == "tandy") { machine = MCH_TANDY; } + else if (mtype == "pcjr") { machine = MCH_PCJR; } + else if (mtype == "hercules") { machine = MCH_HERC; } + else if (mtype == "ega") { machine = MCH_EGA; } + else if (mtype == "vga") { svgaCard = SVGA_S3Trio; } + else if (mtype == "vga_s3") { svgaCard = SVGA_S3Trio; } + else if (mtype == "vesa_nolfb") { svgaCard = SVGA_S3Trio; int10.vesa_nolfb = true;} + else if (mtype == "vga_et4000") { svgaCard = SVGA_TsengET4K; } + else if (mtype == "vga_et3000") { svgaCard = SVGA_TsengET3K; } + else if (mtype == "vga_pvga1a") { svgaCard = SVGA_ParadisePVGA1A; } + else if (mtype == "vga_paradise") { svgaCard = SVGA_ParadisePVGA1A; } + else if (mtype == "vgaonly") { svgaCard = SVGA_None; } + else E_Exit("DOSBOX:Unknown machine type %s",mtype.c_str()); } void DOSBOX_Init(void) { Section_prop * secprop; Section_line * secline; + Prop_int* Pint; + Prop_hex* Phex; + Prop_string* Pstring; + Prop_bool* Pbool; + Prop_multival* Pmulti; SDLNetInited = false; + // Some frequently used option sets + const char *rates[] = { "22050", "44100", "48000", "32000", "16000", "11025", "8000", 0 }; + const char *ios[] = { "220", "240", "260", "280", "2a0", "2c0", "2e0", "300", 0 }; + const char *irqs[] = { "3", "5", "7", "9", "10", "11", "12", 0 }; + const char *dmas[] = { "0", "1", "3", "5", "6", "7", 0 }; + + /* Setup all the different modules making up DOSBox */ - + const char* machines[] = { + "hercules", "cga"," tandy", "pcjr", "ega", "vga", + "vgaonly", "vga_s3", "vga_et3000", "vga_et4000", + "vga_pvga1a", "vga_paradise", "vesa_nolfb", 0 }; secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit); - secprop->Add_string("language",""); - secprop->Add_string("machine","vga"); - secprop->Add_string("captures","capture"); + Pstring = secprop->Add_string("language",Property::Changeable::Always,""); + Pstring->Set_help("Select another language file."); + + Pstring = secprop->Add_string("machine",Property::Changeable::OnlyAtStart,"vga"); + Pstring->Set_values(machines); + Pstring->Set_help("The type of machine tries to emulate."); + + Pstring = secprop->Add_string("captures",Property::Changeable::Always,"capture"); + Pstring->Set_help("Directory where things like wave, midi, screenshot get captured."); #if C_DEBUG LOG_StartUp(); @@ -330,58 +339,75 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&PAGING_Init);//done secprop->AddInitFunction(&MEM_Init);//done secprop->AddInitFunction(&HARDWARE_Init);//done - secprop->Add_int("memsize",16); + Pint = secprop->Add_int("memsize", Property::Changeable::WhenIdle,16); + Pint->SetMinMax(1,63); + Pint->Set_help("Amount of memory DOSBox has in megabytes."); secprop->AddInitFunction(&CALLBACK_Init); secprop->AddInitFunction(&PIC_Init);//done secprop->AddInitFunction(&PROGRAMS_Init); secprop->AddInitFunction(&TIMER_Init);//done secprop->AddInitFunction(&CMOS_Init);//done - - MSG_Add("DOSBOX_CONFIGFILE_HELP", - "language -- Select another language file.\n" - "memsize -- Amount of memory DOSBox has in megabytes.\n" - "machine -- The type of machine tries to emulate:hercules,cga,tandy,pcjr,vga.\n" - "captures -- Directory where things like wave,midi,screenshot get captured.\n" - ); secprop=control->AddSection_prop("render",&RENDER_Init,true); - secprop->Add_int("frameskip",0); - secprop->Add_bool("aspect",false); - secprop->Add_string("scaler","normal2x"); - MSG_Add("RENDER_CONFIGFILE_HELP", - "frameskip -- How many frames DOSBox skips before drawing one.\n" - "aspect -- Do aspect correction, if your output method doesn't support scaling this can slow things down!.\n" - "scaler -- Scaler used to enlarge/enhance low resolution modes.\n" - " Supported are none,normal2x,normal3x,advmame2x,advmame3x,hq2x,hq3x,\n" - " 2xsai,super2xsai,supereagle,advinterp2x,advinterp3x,\n" - " tv2x,tv3x,rgb2x,rgb3x,scan2x,scan3x.\n" - " If forced is appended (like scaler=hq2x forced), the scaler will be used\n" - " even if the result might not be desired.\n" - ); + Pint = secprop->Add_int("frameskip",Property::Changeable::Always,0); + Pint->SetMinMax(0,10); + Pint->Set_help("How many frames DOSBox skips before drawing one."); + + Pbool = secprop->Add_bool("aspect",Property::Changeable::Always,false); + Pbool->Set_help("Do aspect correction, if your output method doesn't support scaling this can slow things down!."); + + Pmulti = secprop->Add_multi("scaler",Property::Changeable::Always," "); + Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended,the scaler will be used even if the result might not be desired."); + Pstring = Pmulti->GetSection()->Add_string("type",Property::Changeable::Always,"normal2x"); + + const char *scalers[] = { + "none", "normal2x", "normal3x", +#if RENDER_USE_ADVANCED_SCALERS>2 + "advmame2x", "advmame3x", "advinterp2x", "advinterp3x", "hq2x", "hq3x", "2xsai", "super2xsai", "supereagle", +#endif +#if RENDER_USE_ADVANCED_SCALERS>0 + "tv2x", "tv3x", "rgb2x", "rgb3x", "scan2x", "scan3x", +#endif + 0 }; + Pstring->Set_values(scalers); + + const char* force[] = { "", "forced", 0 }; + Pstring = Pmulti->GetSection()->Add_string("force",Property::Changeable::Always,""); + Pstring->Set_values(force); secprop=control->AddSection_prop("cpu",&CPU_Init,true);//done + const char* cores[] = { "auto", #if (C_DYNAMIC_X86) || (C_DYNREC) - secprop->Add_string("core","auto"); -#else - secprop->Add_string("core","normal"); + "dynamic", #endif - secprop->Add_string("cycles","auto"); - secprop->Add_int("cycleup",500); - secprop->Add_int("cycledown",20); - MSG_Add("CPU_CONFIGFILE_HELP", - "core -- CPU Core used in emulation: normal,simple" -#if (C_DYNAMIC_X86) || (C_DYNREC) - ",dynamic,auto.\n" - " auto switches from normal to dynamic if appropriate" -#endif - ".\n" - "cycles -- Amount of instructions DOSBox tries to emulate each millisecond.\n" - " Setting this value too high results in sound dropouts and lags.\n" - " You can also let DOSBox guess the correct value by setting it to max.\n" - " The default setting (auto) switches to max if appropriate.\n" - "cycleup -- Amount of cycles to increase/decrease with keycombo.\n" - "cycledown Setting it lower than 100 will be a percentage.\n" - ); + "normal", "simple",0 }; + Pstring = secprop->Add_string("core",Property::Changeable::WhenIdle,"auto"); + Pstring->Set_values(cores); + Pstring->Set_help("CPU Core used in emulation. auto will switch to dynamic if available and appropriate."); + + Pmulti = secprop->Add_multi("cycles",Property::Changeable::Always," "); + Pmulti->Set_help( + "Amount of instructions DOSBox tries to emulate each millisecond. Setting this value too high results in sound dropouts and lags. Cycles can be set in 3 ways:" + " 'auto' tries to guess what a game needs.\n" + " It usually works, but can fail for certain games.\n" + " 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails.\n" + " (Example: fixed 4000)\n" + " 'max' will allocate as much cycles as your computer is able to handle\n"); + + const char* cyclest[] = { "auto","fixed","max" }; + Pstring = Pmulti->GetSection()->Add_string("type",Property::Changeable::Always,"auto"); + Pstring->Set_values(cyclest); + + Pstring = Pmulti->GetSection()->Add_string("parameters",Property::Changeable::Always,""); + + Pint = secprop->Add_int("cycleup",Property::Changeable::Always,500); + Pint->SetMinMax(1,1000000); + Pint->Set_help("Amount of cycles to increase/decrease with keycombo."); + + Pint = secprop->Add_int("cycledown",Property::Changeable::Always,20); + Pint->SetMinMax(1,1000000); + Pint->Set_help("Setting it lower than 100 will be a percentage."); + #if C_FPU secprop->AddInitFunction(&FPU_Init); #endif @@ -390,168 +416,229 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&KEYBOARD_Init); secprop=control->AddSection_prop("mixer",&MIXER_Init); - secprop->Add_bool("nosound",false); - secprop->Add_int("rate",22050); - secprop->Add_int("blocksize",2048); - secprop->Add_int("prebuffer",10); + Pbool = secprop->Add_bool("nosound",Property::Changeable::OnlyAtStart,false); + Pbool->Set_help("Enable silent mode, sound is still emulated though."); - MSG_Add("MIXER_CONFIGFILE_HELP", - "nosound -- Enable silent mode, sound is still emulated though.\n" - "rate -- Mixer sample rate, setting any devices higher than this will\n" - " probably lower their sound quality.\n" - "blocksize -- Mixer block size, larger blocks might help sound stuttering\n" - " but sound will also be more lagged.\n" - "prebuffer -- How many milliseconds of data to keep on top of the blocksize.\n" - ); + Pint = secprop->Add_int("rate",Property::Changeable::OnlyAtStart,22050); + Pint->Set_values(rates); + Pint->Set_help("Mixer sample rate, setting any devices higher than this will probably lower their sound quality."); + + const char *blocksizes[] = { + "2048", "4096", "8192", "1024", "512", "256", 0}; + Pint = secprop->Add_int("blocksize",Property::Changeable::OnlyAtStart,2048); + Pint->Set_values(blocksizes); + Pint->Set_help("Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged."); + + Pint = secprop->Add_int("prebuffer",Property::Changeable::OnlyAtStart,10); + Pint->SetMinMax(0,100); + Pint->Set_help("How many milliseconds of data to keep on top of the blocksize."); secprop=control->AddSection_prop("midi",&MIDI_Init,true);//done secprop->AddInitFunction(&MPU401_Init,true);//done - secprop->Add_string("mpu401","intelligent"); - secprop->Add_string("device","default"); - secprop->Add_string("config",""); - MSG_Add("MIDI_CONFIGFILE_HELP", - "mpu401 -- Type of MPU-401 to emulate: none, uart or intelligent.\n" - "device -- Device that will receive the MIDI data from MPU-401.\n" - " This can be default,alsa,oss,win32,coreaudio,coremidi,none.\n" - "config -- Special configuration options for the device. In Windows put\n" - " the id of the device you want to use. See README for details.\n" - ); + const char* mputypes[] = { "intelligent", "uart", "none",0}; + // FIXME: add some way to offer the actually available choices. + const char *devices[] = { "default", "win32", "alsa", "oss", "coreaudio", "coremidi","none", 0}; + Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent"); + Pstring->Set_values(mputypes); + Pstring->Set_help("Type of MPU-401 to emulate."); + + Pstring = secprop->Add_string("device",Property::Changeable::WhenIdle,"default"); + Pstring->Set_values(devices); + Pstring->Set_help("Device that will receive the MIDI data from MPU-401."); + + Pstring = secprop->Add_string("config",Property::Changeable::WhenIdle,""); + Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use. See README for details."); #if C_DEBUG secprop=control->AddSection_prop("debug",&DEBUG_Init); #endif secprop=control->AddSection_prop("sblaster",&SBLASTER_Init,true);//done - secprop->Add_string("sbtype","sb16"); - secprop->Add_hex("sbbase",0x220); - secprop->Add_int("irq",7); - secprop->Add_int("dma",1); - secprop->Add_int("hdma",5); - secprop->Add_bool("mixer",true); - secprop->Add_string("oplmode","auto"); - secprop->Add_int("oplrate",22050); + + const char* sbtypes[] = { "sb1", "sb2", "sbpro1", "sbpro2", "sb16", "none", 0 }; + Pstring = secprop->Add_string("sbtype",Property::Changeable::WhenIdle,"sb16"); + Pstring->Set_values(sbtypes); + Pstring->Set_help("Type of sblaster to emulate."); + + Phex = secprop->Add_hex("sbbase",Property::Changeable::WhenIdle,0x220); + Phex->Set_values(ios); + Phex->Set_help("The IO address of the soundblaster."); + + Pint = secprop->Add_int("irq",Property::Changeable::WhenIdle,7); + Pint->Set_values(irqs); + Pint->Set_help("The IRQ number of the soundblaster."); + + Pint = secprop->Add_int("dma",Property::Changeable::WhenIdle,1); + Pint->Set_values(dmas); + Pint->Set_help("The DMA number of the soundblaster."); + + Pint = secprop->Add_int("hdma",Property::Changeable::WhenIdle,5); + Pint->Set_values(dmas); + Pint->Set_help("The High DMA number of the soundblaster."); + + Pbool = secprop->Add_bool("mixer",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Allow the soundblaster mixer to modify the DOSBox mixer."); + + const char* opltypes[]={ "auto", "cms", "opl2", "dualopl2", "opl3", "none", 0}; + Pstring = secprop->Add_string("oplmode",Property::Changeable::WhenIdle,"auto"); + Pstring->Set_values(opltypes); + Pstring->Set_help("Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'."); + + Pint = secprop->Add_int("oplrate",Property::Changeable::WhenIdle,22050); + Pint->Set_values(rates); + Pint->Set_help("Sample rate of OPL music emulation."); - MSG_Add("SBLASTER_CONFIGFILE_HELP", - "sbtype -- Type of sblaster to emulate:none,sb1,sb2,sbpro1,sbpro2,sb16.\n" - "sbbase,irq,dma,hdma -- The IO/IRQ/DMA/High DMA address of the soundblaster.\n" - "mixer -- Allow the soundblaster mixer to modify the DOSBox mixer.\n" - "oplmode -- Type of OPL emulation: auto,cms,opl2,dualopl2,opl3.\n" - " On auto the mode is determined by sblaster type.\n" - " All OPL modes are 'Adlib', except for CMS.\n" - "oplrate -- Sample rate of OPL music emulation.\n" - ); secprop=control->AddSection_prop("gus",&GUS_Init,true); //done - secprop->Add_bool("gus",true); - secprop->Add_int("gusrate",22050); - secprop->Add_hex("gusbase",0x240); - secprop->Add_int("irq1",5); - secprop->Add_int("irq2",5); - secprop->Add_int("dma1",3); - secprop->Add_int("dma2",3); - secprop->Add_string("ultradir","C:\\ULTRASND"); + Pbool = secprop->Add_bool("gus",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Enable the Gravis Ultrasound emulation."); - MSG_Add("GUS_CONFIGFILE_HELP", - "gus -- Enable the Gravis Ultrasound emulation.\n" - "gusbase,irq1,irq2,dma1,dma2 -- The IO/IRQ/DMA addresses of the \n" - " Gravis Ultrasound. (Same IRQ's and DMA's are OK.)\n" - "gusrate -- Sample rate of Ultrasound emulation.\n" - "ultradir -- Path to Ultrasound directory. In this directory\n" - " there should be a MIDI directory that contains\n" - " the patch files for GUS playback. Patch sets used\n" - " with Timidity should work fine.\n" - ); + Pint = secprop->Add_int("gusrate",Property::Changeable::WhenIdle,22050); + Pint->Set_values(rates); + Pint->Set_help("Sample rate of Ultrasound emulation."); + + Phex = secprop->Add_hex("gusbase",Property::Changeable::WhenIdle,0x240); + Phex->Set_values(ios); + Phex->Set_help("The IO addresses of the Gravis Ultrasound."); + + Pint = secprop->Add_int("irq1",Property::Changeable::WhenIdle,5); + Pint->Set_values(irqs); + Pint->Set_help("The first IRQ number of the Gravis Ultrasound. (Same IRQs are OK.)"); + + Pint = secprop->Add_int("irq2",Property::Changeable::WhenIdle,5); + Pint->Set_values(irqs); + Pint->Set_help("The second IRQ number of the Gravis Ultrasound. (Same IRQs are OK.)"); + + Pint = secprop->Add_int("dma1",Property::Changeable::WhenIdle,3); + Pint->Set_values(dmas); + Pint->Set_help("The first DMA addresses of the Gravis Ultrasound. (Same DMAs are OK.)"); + + Pint = secprop->Add_int("dma2",Property::Changeable::WhenIdle,3); + Pint->Set_values(dmas); + Pint->Set_help("The second DMA addresses of the Gravis Ultrasound. (Same DMAs are OK.)"); + + Pstring = secprop->Add_string("ultradir",Property::Changeable::WhenIdle,"C:\\ULTRASND"); + Pstring->Set_help( + "Path to Ultrasound directory. In this directory\n" + "there should be a MIDI directory that contains\n" + "the patch files for GUS playback. Patch sets used\n" + "with Timidity should work fine."); + + secprop = control->AddSection_prop("speaker",&PCSPEAKER_Init,true);//done + Pbool = secprop->Add_bool("pcspeaker",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Enable PC-Speaker emulation."); + + Pint = secprop->Add_int("pcrate",Property::Changeable::WhenIdle,22050); + Pint->Set_values(rates); + Pint->Set_help("Sample rate of the PC-Speaker sound generation."); - secprop=control->AddSection_prop("speaker",&PCSPEAKER_Init,true);//done - secprop->Add_bool("pcspeaker",true); - secprop->Add_int("pcrate",22050); secprop->AddInitFunction(&TANDYSOUND_Init,true);//done - secprop->Add_string("tandy","auto"); - secprop->Add_int("tandyrate",22050); - secprop->AddInitFunction(&DISNEY_Init,true);//done - secprop->Add_bool("disney",true); + const char* tandys[] = { "auto", "on", "off", 0}; + Pstring = secprop->Add_string("tandy",Property::Changeable::WhenIdle,"auto"); + Pstring->Set_values(tandys); + Pstring->Set_help("Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'."); + + Pint = secprop->Add_int("tandyrate",Property::Changeable::WhenIdle,22050); + Pint->Set_values(rates); + Pint->Set_help("Sample rate of the Tandy 3-Voice generation."); - MSG_Add("SPEAKER_CONFIGFILE_HELP", - "pcspeaker -- Enable PC-Speaker emulation.\n" - "pcrate -- Sample rate of the PC-Speaker sound generation.\n" - "tandy -- Enable Tandy Sound System emulation (off,on,auto).\n" - " For auto Tandysound emulation is present only if machine is set to tandy.\n" - "tandyrate -- Sample rate of the Tandy 3-Voice generation.\n" - "disney -- Enable Disney Sound Source emulation. Covox Voice Master and Speech Thing compatible.\n" - ); + secprop->AddInitFunction(&DISNEY_Init,true);//done + + Pbool = secprop->Add_bool("disney",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible)."); secprop=control->AddSection_prop("joystick",&BIOS_Init,false);//done - MSG_Add("JOYSTICK_CONFIGFILE_HELP", - "joysticktype -- Type of joystick to emulate: auto (default), none,\n" - " 2axis (supports two joysticks,\n" - " 4axis (supports one joystick, first joystick used),\n" - " 4axis_2 (supports one joystick, second joystick used),\n" - " fcs (Thrustmaster), ch (CH Flightstick).\n" - " none disables joystick emulation.\n" - " auto chooses emulation depending on real joystick(s).\n" - "timed -- enable timed intervals for axis. (false is old style behaviour).\n" - "autofire -- continuously fires as long as you keep the button pressed.\n" - "swap34 -- swap the 3rd and the 4th axis. can be useful for certain joysticks.\n" - "buttonwrap -- enable button wrapping at the number of emulated buttons.\n" - ); - secprop->AddInitFunction(&INT10_Init); secprop->AddInitFunction(&MOUSE_Init); //Must be after int10 as it uses CurMode secprop->AddInitFunction(&JOYSTICK_Init); - secprop->Add_string("joysticktype","auto"); - secprop->Add_bool("timed",true); - secprop->Add_bool("autofire",false); - secprop->Add_bool("swap34",false); - secprop->Add_bool("buttonwrap",true); + const char* joytypes[] = { "auto", "2axis", "4axis", "4axis_2", "fcs", "ch", "none",0}; + Pstring = secprop->Add_string("joysticktype",Property::Changeable::WhenIdle,"auto"); + Pstring->Set_values(joytypes); + Pstring->Set_help( + "Type of joystick to emulate: auto (default), none,\n" + "2axis (supports two joysticks),\n" + "4axis (supports one joystick, first joystick used),\n" + "4axis_2 (supports one joystick, second joystick used),\n" + "fcs (Thrustmaster), ch (CH Flightstick).\n" + "none disables joystick emulation.\n" + "auto chooses emulation depending on real joystick(s)."); + + Pbool = secprop->Add_bool("timed",Property::Changeable::WhenIdle,true); + Pbool->Set_help("enable timed intervals for axis. (false is old style behaviour)."); + + Pbool = secprop->Add_bool("autofire",Property::Changeable::WhenIdle,false); + Pbool->Set_help("continuously fires as long as you keep the button pressed."); + + Pbool = secprop->Add_bool("swap34",Property::Changeable::WhenIdle,false); + Pbool->Set_help("swap the 3rd and the 4th axis. can be useful for certain joysticks."); + + Pbool = secprop->Add_bool("buttonwrap",Property::Changeable::WhenIdle,true); + Pbool->Set_help("enable button wrapping at the number of emulated buttons."); - // had to rename these to serial due to conflicts in config secprop=control->AddSection_prop("serial",&SERIAL_Init,true); - secprop->Add_string("serial1","dummy"); - secprop->Add_string("serial2","dummy"); - secprop->Add_string("serial3","disabled"); - secprop->Add_string("serial4","disabled"); - MSG_Add("SERIAL_CONFIGFILE_HELP", - "serial1-4 -- set type of device connected to com port.\n" - " Can be disabled, dummy, modem, nullmodem, directserial.\n" - " Additional parameters must be in the same line in the form of\n" - " parameter:value. Parameter for all types is irq.\n" - " for directserial: realport (required), rxdelay (optional).\n" - " for modem: listenport (optional).\n" - " for nullmodem: server, rxdelay, txdelay, telnet, usedtr,\n" - " transparent, port, inhsocket (all optional).\n" - " Example: serial1=modem listenport:5000\n" - ); + const char* serials[] = { "dummy", "disabled", "modem", "nullmodem", +#if defined(WIN32) || defined(OS2) + "directserial realport:COM1", "directserial realport:COM2", +#else + "directserial realport:ttyS0", "directserial realport:ttyS1", +#endif + 0}; + + Pstring = secprop->Add_string("serial1",Property::Changeable::WhenIdle,"dummy"); + Pstring->Set_values(serials); + Pstring->Set_help( + "set type of device connected to com port.\n" + "Can be disabled, dummy, modem, nullmodem, directserial.\n" + "Additional parameters must be in the same line in the form of\n" + "parameter:value. Parameter for all types is irq.\n" + "for directserial: realport (required), rxdelay (optional).\n" + "for modem: listenport (optional).\n" + "for nullmodem: server, rxdelay, txdelay, telnet, usedtr,\n" + " transparent, port, inhsocket (all optional).\n" + "Example: serial1=modem listenport:5000"); + + Pstring = secprop->Add_string("serial2",Property::Changeable::WhenIdle,"dummy"); + Pstring->Set_values(serials); + Pstring->Set_help("see serial1"); + + Pstring = secprop->Add_string("serial3",Property::Changeable::WhenIdle,"disabled"); + Pstring->Set_values(serials); + Pstring->Set_help("see serial1"); + + Pstring = secprop->Add_string("serial4",Property::Changeable::WhenIdle,"disabled"); + Pstring->Set_values(serials); + Pstring->Set_help("see serial1"); /* All the DOS Related stuff, which will eventually start up in the shell */ - //TODO Maybe combine most of the dos stuff in one section like ems,xms secprop=control->AddSection_prop("dos",&DOS_Init,false);//done secprop->AddInitFunction(&XMS_Init,true);//done - secprop->Add_bool("xms",true); + Pbool = secprop->Add_bool("xms",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Enable XMS support."); + secprop->AddInitFunction(&EMS_Init,true);//done - secprop->Add_bool("ems",true); - secprop->Add_bool("umb",true); + Pbool = secprop->Add_bool("ems",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Enable EMS support."); + + Pbool = secprop->Add_bool("umb",Property::Changeable::WhenIdle,true); + Pbool->Set_help("Enable UMB support."); + secprop->AddInitFunction(&DOS_KeyboardLayout_Init,true); - secprop->Add_string("keyboardlayout", "none"); - MSG_Add("DOS_CONFIGFILE_HELP", - "xms -- Enable XMS support.\n" - "ems -- Enable EMS support.\n" - "umb -- Enable UMB support.\n" - "keyboardlayout -- Language code of the keyboard layout (or none).\n" - ); + Pstring = secprop->Add_string("keyboardlayout",Property::Changeable::WhenIdle, "none"); + Pstring->Set_help("Language code of the keyboard layout (or none)."); + // Mscdex secprop->AddInitFunction(&MSCDEX_Init); secprop->AddInitFunction(&DRIVES_Init); secprop->AddInitFunction(&CDROM_Image_Init); #if C_IPX secprop=control->AddSection_prop("ipx",&IPX_Init,true); - secprop->Add_bool("ipx", false); - MSG_Add("IPX_CONFIGFILE_HELP", - "ipx -- Enable ipx over UDP/IP emulation.\n" - ); + Pbool = secprop->Add_bool("ipx",Property::Changeable::WhenIdle, false); + Pbool->Set_help("Enable ipx over UDP/IP emulation."); #endif // secprop->AddInitFunction(&CREDITS_Init); + //TODO ? secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); MSG_Add("AUTOEXEC_CONFIGFILE_HELP", "Lines in this section will be run at startup.\n" diff --git a/src/gui/render.cpp b/src/gui/render.cpp index a3de853d..698a8376 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: render.cpp,v 1.55 2007-08-11 12:19:00 qbix79 Exp $ */ +/* $Id: render.cpp,v 1.56 2008-02-10 11:14:03 qbix79 Exp $ */ #include #include @@ -571,53 +571,43 @@ void RENDER_Init(Section * sec) { render.aspect=section->Get_bool("aspect"); render.frameskip.max=section->Get_int("frameskip"); render.frameskip.count=0; - const char * scaler; std::string cline; - std::string scaler_str; + std::string scaler; + //Check for commandline paramters and parse them through the configclass so they get checked against allowed values if (control->cmdline->FindString("-scaler",cline,false)) { - scaler=cline.c_str(); - render.scale.forced=false; + section->HandleInputline(std::string("scaler=") + cline); } else if (control->cmdline->FindString("-forcescaler",cline,false)) { - scaler=cline.c_str(); - render.scale.forced=true; - } else { - CommandLine cmd(0,section->Get_string("scaler")); - cmd.FindCommand(1,scaler_str); - scaler=scaler_str.c_str(); - render.scale.forced=false; - if (cmd.GetCount()>1) { - std::string str; - if (cmd.FindCommand(2,str)) { - if (str=="forced") render.scale.forced=true; - } - } + section->HandleInputline(std::string("scaler=") + cline + " forced"); } - if (!strcasecmp(scaler,"none")) { render.scale.op = scalerOpNormal;render.scale.size = 1; } - else if (!strcasecmp(scaler,"normal2x")) { render.scale.op = scalerOpNormal;render.scale.size = 2; } - else if (!strcasecmp(scaler,"normal3x")) { render.scale.op = scalerOpNormal;render.scale.size = 3; } + + Prop_multival* prop = section->Get_multival("scaler"); + scaler = prop->GetSection()->Get_string("type"); + std::string f = prop->GetSection()->Get_string("force"); + render.scale.forced = false; + if(f == "forced") render.scale.forced = true; + + if (scaler == "none") { render.scale.op = scalerOpNormal;render.scale.size = 1; } + else if (scaler == "normal2x") { render.scale.op = scalerOpNormal;render.scale.size = 2; } + else if (scaler == "normal3x") { render.scale.op = scalerOpNormal;render.scale.size = 3; } #if RENDER_USE_ADVANCED_SCALERS>2 - else if (!strcasecmp(scaler,"advmame2x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 2; } - else if (!strcasecmp(scaler,"advmame3x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 3; } - else if (!strcasecmp(scaler,"advinterp2x")) { render.scale.op = scalerOpAdvInterp;render.scale.size = 2; } - else if (!strcasecmp(scaler,"advinterp3x")) { render.scale.op = scalerOpAdvInterp;render.scale.size = 3; } - else if (!strcasecmp(scaler,"hq2x")) { render.scale.op = scalerOpHQ;render.scale.size = 2; } - else if (!strcasecmp(scaler,"hq3x")) { render.scale.op = scalerOpHQ;render.scale.size = 3; } - else if (!strcasecmp(scaler,"2xsai")) { render.scale.op = scalerOpSaI;render.scale.size = 2; } - else if (!strcasecmp(scaler,"super2xsai")) { render.scale.op = scalerOpSuperSaI;render.scale.size = 2; } - else if (!strcasecmp(scaler,"supereagle")) { render.scale.op = scalerOpSuperEagle;render.scale.size = 2; } + else if (scaler == "advmame2x") { render.scale.op = scalerOpAdvMame;render.scale.size = 2; } + else if (scaler == "advmame3x") { render.scale.op = scalerOpAdvMame;render.scale.size = 3; } + else if (scaler == "advinterp2x") { render.scale.op = scalerOpAdvInterp;render.scale.size = 2; } + else if (scaler == "advinterp3x") { render.scale.op = scalerOpAdvInterp;render.scale.size = 3; } + else if (scaler == "hq2x") { render.scale.op = scalerOpHQ;render.scale.size = 2; } + else if (scaler == "hq3x") { render.scale.op = scalerOpHQ;render.scale.size = 3; } + else if (scaler == "2xsai") { render.scale.op = scalerOpSaI;render.scale.size = 2; } + else if (scaler == "super2xsai") { render.scale.op = scalerOpSuperSaI;render.scale.size = 2; } + else if (scaler == "supereagle") { render.scale.op = scalerOpSuperEagle;render.scale.size = 2; } #endif #if RENDER_USE_ADVANCED_SCALERS>0 - else if (!strcasecmp(scaler,"tv2x")) { render.scale.op = scalerOpTV;render.scale.size = 2; } - else if (!strcasecmp(scaler,"tv3x")) { render.scale.op = scalerOpTV;render.scale.size = 3; } - else if (!strcasecmp(scaler,"rgb2x")){ render.scale.op = scalerOpRGB;render.scale.size = 2; } - else if (!strcasecmp(scaler,"rgb3x")){ render.scale.op = scalerOpRGB;render.scale.size = 3; } - else if (!strcasecmp(scaler,"scan2x")){ render.scale.op = scalerOpScan;render.scale.size = 2; } - else if (!strcasecmp(scaler,"scan3x")){ render.scale.op = scalerOpScan;render.scale.size = 3; } + else if (scaler == "tv2x") { render.scale.op = scalerOpTV;render.scale.size = 2; } + else if (scaler == "tv3x") { render.scale.op = scalerOpTV;render.scale.size = 3; } + else if (scaler == "rgb2x"){ render.scale.op = scalerOpRGB;render.scale.size = 2; } + else if (scaler == "rgb3x"){ render.scale.op = scalerOpRGB;render.scale.size = 3; } + else if (scaler == "scan2x"){ render.scale.op = scalerOpScan;render.scale.size = 2; } + else if (scaler == "scan3x"){ render.scale.op = scalerOpScan;render.scale.size = 3; } #endif - else { - render.scale.op = scalerOpNormal;render.scale.size = 1; - LOG_MSG("Illegal scaler type %s,falling back to normal.",scaler); - } //If something changed that needs a ReInit // Only ReInit when there is a src.bpp (fixes crashes on startup and directly changing the scaler without a screen specified yet) diff --git a/src/gui/sdl_gui.cpp b/src/gui/sdl_gui.cpp index 6a1a900c..4197ff59 100644 --- a/src/gui/sdl_gui.cpp +++ b/src/gui/sdl_gui.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdl_gui.cpp,v 1.4 2008-01-26 15:50:19 qbix79 Exp $ */ +/* $Id: sdl_gui.cpp,v 1.5 2008-02-10 11:14:03 qbix79 Exp $ */ #include "SDL.h" #include "../libs/gui_tk/gui_tk.h" @@ -281,11 +281,11 @@ public: PropertyEditorBool(Window *parent, int x, int y, Section_prop *section, Property *prop) : PropertyEditor(parent, x, y, section, prop) { input = new GUI::Checkbox(this, 0, 3, prop->propname.c_str()); - input->setChecked(prop->GetValue()._bool); + input->setChecked(static_cast(prop->GetValue())); } bool prepare(std::string &buffer) { - if (input->isChecked() == prop->GetValue()._bool) return false; + if (input->isChecked() == static_cast(prop->GetValue())) return false; buffer.append(input->isChecked()?"true":"false"); return true; } @@ -299,11 +299,13 @@ public: PropertyEditor(parent, x, y, section, prop) { new GUI::Label(this, 0, 5, prop->propname); input = new GUI::Input(this, 130, 0, 110); - input->setText(prop->GetValue()._string); + std::string temps = prop->GetValue().ToString(); + input->setText(stringify(temps)); } bool prepare(std::string &buffer) { - if (input->getText() == GUI::String(prop->GetValue()._string)) return false; + std::string temps = prop->GetValue().ToString(); + if (input->getText() == GUI::String(temps)) return false; buffer.append(static_cast(input->getText())); return true; } @@ -337,13 +339,14 @@ public: PropertyEditor(parent, x, y, section, prop) { new GUI::Label(this, 0, 5, prop->propname); input = new GUI::Input(this, 130, 0, 50); - input->setText(stringify(prop->GetValue()._hex, std::hex)); + std::string temps = prop->GetValue().ToString(); + input->setText(temps.c_str()); } bool prepare(std::string &buffer) { int val; convert(input->getText(), val, false, std::hex); - if (val == prop->GetValue()._hex) return false; + if ((Hex)val == prop->GetValue()) return false; buffer.append(stringify(val, std::hex)); return true; } @@ -357,13 +360,14 @@ public: PropertyEditor(parent, x, y, section, prop) { new GUI::Label(this, 0, 5, prop->propname); input = new GUI::Input(this, 130, 0, 50); - input->setText(stringify(prop->GetValue()._int)); + //Maybe use ToString() of Value + input->setText(stringify(static_cast(prop->GetValue()))); } bool prepare(std::string &buffer) { int val; convert(input->getText(), val, false); - if (val == prop->GetValue()._int) return false; + if (val == static_cast(prop->GetValue())) return false; buffer.append(stringify(val)); return true; } diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 64c5ddaa..3a1486ae 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdlmain.cpp,v 1.138 2008-01-16 20:17:15 c2woody Exp $ */ +/* $Id: sdlmain.cpp,v 1.139 2008-02-10 11:14:03 qbix79 Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -938,48 +938,29 @@ static void GUI_StartUp(Section * sec) { sdl.desktop.fullscreen=section->Get_bool("fullscreen"); sdl.wait_on_error=section->Get_bool("waitonerror"); - const char * priority=section->Get_string("priority"); - if (priority && priority[0]) { - Bitu next; - if (!strncasecmp(priority,"lowest",6)) { - sdl.priority.focus=PRIORITY_LEVEL_LOWEST;next=6; - } else if (!strncasecmp(priority,"lower",5)) { - sdl.priority.focus=PRIORITY_LEVEL_LOWER;next=5; - } else if (!strncasecmp(priority,"normal",6)) { - sdl.priority.focus=PRIORITY_LEVEL_NORMAL;next=6; - } else if (!strncasecmp(priority,"higher",6)) { - sdl.priority.focus=PRIORITY_LEVEL_HIGHER;next=6; - } else if (!strncasecmp(priority,"highest",7)) { - sdl.priority.focus=PRIORITY_LEVEL_HIGHEST;next=7; - } else { - next=0;sdl.priority.focus=PRIORITY_LEVEL_HIGHER; - } - priority=&priority[next]; - if (next && priority[0]==',' && priority[1]) { - priority++; - if (!strncasecmp(priority,"lowest",6)) { - sdl.priority.nofocus=PRIORITY_LEVEL_LOWEST; - } else if (!strncasecmp(priority,"lower",5)) { - sdl.priority.nofocus=PRIORITY_LEVEL_LOWER; - } else if (!strncasecmp(priority,"normal",6)) { - sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; - } else if (!strncasecmp(priority,"higher",6)) { - sdl.priority.nofocus=PRIORITY_LEVEL_HIGHER; - } else if (!strncasecmp(priority,"highest",7)) { - sdl.priority.nofocus=PRIORITY_LEVEL_HIGHEST; - } else if (!strncasecmp(priority,"pause",5)) { - /* we only check for pause here, because it makes no sense - * for DOSBox to be paused while it has focus - */ - sdl.priority.nofocus=PRIORITY_LEVEL_PAUSE; - } else { - sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; - } - } else sdl.priority.nofocus=sdl.priority.focus; - } else { - sdl.priority.focus=PRIORITY_LEVEL_HIGHER; - sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; + + Prop_multival* p=section->Get_multival("priority"); + std::string focus = p->GetSection()->Get_string("active"); + std::string notfocus = p->GetSection()->Get_string("inactive"); + + if (focus == "lowest") { sdl.priority.focus = PRIORITY_LEVEL_LOWEST; } + else if (focus == "lower") { sdl.priority.focus = PRIORITY_LEVEL_LOWER; } + else if (focus == "normal") { sdl.priority.focus = PRIORITY_LEVEL_NORMAL; } + else if (focus == "higher") { sdl.priority.focus = PRIORITY_LEVEL_HIGHER; } + else if (focus == "highest") { sdl.priority.focus = PRIORITY_LEVEL_HIGHEST; } + + if (notfocus == "lowest") { sdl.priority.nofocus=PRIORITY_LEVEL_LOWEST; } + else if (notfocus == "lower") { sdl.priority.nofocus=PRIORITY_LEVEL_LOWER; } + else if (notfocus == "normal") { sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; } + else if (notfocus == "higher") { sdl.priority.nofocus=PRIORITY_LEVEL_HIGHER; } + else if (notfocus == "highest") { sdl.priority.nofocus=PRIORITY_LEVEL_HIGHEST; } + else if (notfocus == "pause") { + /* we only check for pause here, because it makes no sense + * for DOSBox to be paused while it has focus + */ + sdl.priority.nofocus=PRIORITY_LEVEL_PAUSE; } + SetPriority(sdl.priority.focus); //Assume focus on startup sdl.mouse.locked=false; mouselocked=false; //Global for mapper @@ -1038,30 +1019,30 @@ static void GUI_StartUp(Section * sec) { if (!sdl.mouse.autoenable) SDL_ShowCursor(SDL_DISABLE); sdl.mouse.autolock=false; sdl.mouse.sensitivity=section->Get_int("sensitivity"); - const char * output=section->Get_string("output"); + std::string output=section->Get_string("output"); /* Setup Mouse correctly if fullscreen */ if(sdl.desktop.fullscreen) GFX_CaptureMouse(); - if (!strcasecmp(output,"surface")) { + if (output == "surface") { sdl.desktop.want_type=SCREEN_SURFACE; #if (HAVE_DDRAW_H) && defined(WIN32) - } else if (!strcasecmp(output,"ddraw")) { + } else if (output == "ddraw") { sdl.desktop.want_type=SCREEN_SURFACE_DDRAW; #endif - } else if (!strcasecmp(output,"overlay")) { + } else if (output == "overlay") { sdl.desktop.want_type=SCREEN_OVERLAY; #if C_OPENGL - } else if (!strcasecmp(output,"opengl")) { + } else if (output == "opengl") { sdl.desktop.want_type=SCREEN_OPENGL; sdl.opengl.bilinear=true; - } else if (!strcasecmp(output,"openglnb")) { + } else if (output == "openglnb") { sdl.desktop.want_type=SCREEN_OPENGL; sdl.opengl.bilinear=false; #endif } else { - LOG_MSG("SDL:Unsupported output device %s, switching back to surface",output); - sdl.desktop.want_type=SCREEN_SURFACE; + LOG_MSG("SDL:Unsupported output device %s, switching back to surface",output.c_str()); + sdl.desktop.want_type=SCREEN_SURFACE;//SHOULDN'T BE POSSIBLE anymore } sdl.overlay=0; @@ -1233,10 +1214,10 @@ void GFX_Events() { GFX_SetTitle(-1,-1,true); KEYBOARD_ClrBuffer(); - SDL_Delay(500); - while (SDL_PollEvent(&ev)) { +// SDL_Delay(500); +// while (SDL_PollEvent(&ev)) { // flush event queue. - } +// } while (paused) { // WaitEvent waits for an event rather than polling, so CPU usage drops to zero @@ -1433,39 +1414,62 @@ int main(int argc, char* argv[]) { sdl.num_joysticks=SDL_NumJoysticks(); Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp); sdl_sec->AddInitFunction(&MAPPER_StartUp); - sdl_sec->Add_bool("fullscreen",false); - sdl_sec->Add_bool("fulldouble",false); - sdl_sec->Add_string("fullresolution","original"); - sdl_sec->Add_string("windowresolution","original"); - sdl_sec->Add_string("output","surface"); - sdl_sec->Add_bool("autolock",true); - sdl_sec->Add_int("sensitivity",100); - sdl_sec->Add_bool("waitonerror",true); - sdl_sec->Add_string("priority","higher,normal"); - sdl_sec->Add_string("mapperfile","mapper.txt"); - sdl_sec->Add_bool("usescancodes",true); + Prop_bool* Pbool; + Prop_string* Pstring; + Prop_int* Pint; + Prop_multival* Pmulti; + Pbool = sdl_sec->Add_bool("fullscreen",Property::Changeable::Always,false); + Pbool->Set_help("Start dosbox directly in fullscreen."); - MSG_Add("SDL_CONFIGFILE_HELP", - "fullscreen -- Start dosbox directly in fullscreen.\n" - "fulldouble -- Use double buffering in fullscreen.\n" - "fullresolution -- What resolution to use for fullscreen: original or fixed size (e.g. 1024x768).\n" - "windowresolution -- Scale the window to this size IF the output device supports hardware scaling.\n" - "output -- What to use for output: surface,overlay" + Pbool = sdl_sec->Add_bool("fulldouble",Property::Changeable::Always,false); + Pbool->Set_help("Use double buffering in fullscreen."); + + Pstring = sdl_sec->Add_string("fullresolution",Property::Changeable::Always,"original"); + Pstring->Set_help("What resolution to use for fullscreen: original or fixed size (e.g. 1024x768)."); + + Pstring = sdl_sec->Add_string("windowresolution",Property::Changeable::Always,"original"); + Pstring->Set_help("Scale the window to this size IF the output device supports hardware scaling."); + + const char* outputs[] = { + "surface", "overlay", #if C_OPENGL - ",opengl,openglnb" + "opengl", "openglnb", #endif #if (HAVE_DDRAW_H) && defined(WIN32) - ",ddraw" + "ddraw", #endif - ".\n" - "autolock -- Mouse will automatically lock, if you click on the screen.\n" - "sensitiviy -- Mouse sensitivity.\n" - "waitonerror -- Wait before closing the console if dosbox has an error.\n" - "priority -- Priority levels for dosbox: lowest,lower,normal,higher,highest,pause (when not focussed).\n" - " Second entry behind the comma is for when dosbox is not focused/minimized.\n" - "mapperfile -- File used to load/save the key/event mappings from.\n" - "usescancodes -- Avoid usage of symkeys, might not work on all operating systems.\n" - ); + 0 }; + Pstring = sdl_sec->Add_string("output",Property::Changeable::Always,"surface"); + Pstring->Set_help("What video system to use for output."); + Pstring->Set_values(outputs); + + Pbool = sdl_sec->Add_bool("autolock",Property::Changeable::Always,true); + Pbool->Set_help("Mouse will automatically lock, if you click on the screen."); + + Pint = sdl_sec->Add_int("sensitivity",Property::Changeable::Always,100); + Pint->SetMinMax(1,1000); + Pint->Set_help("Mouse sensitivity."); + + Pbool = sdl_sec->Add_bool("waitonerror",Property::Changeable::Always, true); + Pbool->Set_help("Wait before closing the console if dosbox has an error."); + + Pmulti = sdl_sec->Add_multi("priority", Property::Changeable::Always, ","); + Pmulti->Set_help("priority -- Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. (pause is only valid for the second entry)"); + + const char* actt[] = { "lowest", "lower", "normal", "higher", "highest", "pause", 0}; + Pstring = Pmulti->GetSection()->Add_string("active",Property::Changeable::Always,"higher"); + Pstring->Set_values(actt); + + const char* inactt[] = { "lowest", "lower", "normal", "higher", "highest", "pause", 0}; + Pstring = Pmulti->GetSection()->Add_string("inactive",Property::Changeable::Always,"normal"); + Pstring->Set_values(inactt); + + Pstring = sdl_sec->Add_string("mapperfile",Property::Changeable::Always,"mapper.txt"); + Pstring->Set_help("File used to load/save the key/event mappings from."); + + Pbool = sdl_sec->Add_bool("usescancodes",Property::Changeable::Always,true); + Pbool->Set_help("Avoid usage of symkeys, might not work on all operating systems."); + /* Init all the dosbox subsystems */ DOSBOX_Init(); std::string config_file; diff --git a/src/misc/messages.cpp b/src/misc/messages.cpp index 4d15dc47..259b99ba 100644 --- a/src/misc/messages.cpp +++ b/src/misc/messages.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: messages.cpp,v 1.19 2007-01-08 19:45:41 qbix79 Exp $ */ +/* $Id: messages.cpp,v 1.20 2008-02-10 11:14:03 qbix79 Exp $ */ #include #include @@ -47,10 +47,11 @@ void MSG_Add(const char * _name, const char* _val) { /* Find the message */ for(itmb tel=Lang.begin();tel!=Lang.end();tel++) { if((*tel).name==_name) { + LOG_MSG("double entry for %s",_name); return; } } - /* Even if the message doesn't exist add it */ + /* if the message doesn't exist add it */ Lang.push_back(MessageBlock(_name,_val)); } diff --git a/src/misc/programs.cpp b/src/misc/programs.cpp index 4fd87fbf..79d28b3e 100644 --- a/src/misc/programs.cpp +++ b/src/misc/programs.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: programs.cpp,v 1.29 2007-11-04 19:14:32 c2woody Exp $ */ +/* $Id: programs.cpp,v 1.30 2008-02-10 11:14:03 qbix79 Exp $ */ #include #include @@ -249,13 +249,13 @@ void CONFIG::Run(void) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str()); return; } - char const* val = sec->GetPropValue(prop.c_str()); - if(!val) { + std::string val = sec->GetPropValue(prop.c_str()); + if(val != NO_SUCH_PROPERTY) { WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str()); return; } - WriteOut("%s",val); - first_shell->SetEnv("CONFIG",val); + WriteOut("%s",val.c_str()); + first_shell->SetEnv("CONFIG",val.c_str()); return; } diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index a2937720..3752ab37 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -16,21 +16,22 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: setup.cpp,v 1.43 2008-01-27 18:31:01 qbix79 Exp $ */ +/* $Id: setup.cpp,v 1.44 2008-02-10 11:14:03 qbix79 Exp $ */ #include "dosbox.h" #include "cross.h" #include "setup.h" +#include "support.h" #include #include +#include #include #include #include -#include "support.h" using namespace std; -void Value::destroy() { +void Value::destroy() throw(){ if (type == V_STRING) delete _string; } @@ -43,7 +44,7 @@ Value& Value::copy(Value const& in) throw(WrongType) { return *this; } -void Value::plaincopy(Value const& in) { +void Value::plaincopy(Value const& in) throw(){ type = in.type; _int = in._int; _double = in._double; @@ -59,7 +60,7 @@ Value::operator bool () const throw(WrongType) { Value::operator Hex () const throw(WrongType) { if(type != V_HEX) throw WrongType(); - return _hexn; + return _hex; } Value::operator int () const throw(WrongType) { @@ -88,7 +89,7 @@ bool Value::operator==(Value const& other) { if(_int == other._int) return true; break; case V_HEX: - if(_hexn == other._hexn) return true; + if(_hex == other._hex) return true; break; case V_DOUBLE: if(_double == other._double) return true; @@ -102,108 +103,245 @@ bool Value::operator==(Value const& other) { } return false; } +void Value::SetValue(string const& in,Etype _type) throw(WrongType) { + /* Throw exception if the current type isn't the wanted type + * Unless the wanted type is current. + */ + if(_type == V_CURRENT && type == V_NONE) throw WrongType(); + if(_type != V_CURRENT) { + if(type != V_NONE && type != _type) throw WrongType(); + type = _type; + } + switch(type){ + case V_HEX: + set_hex(in); + break; + case V_INT: + set_int(in); + break; + case V_BOOL: + set_bool(in); + break; + case V_STRING: + set_string(in); + break; + case V_DOUBLE: + set_double(in); + break; + + case V_NONE: + case V_CURRENT: + default: + /* Shouldn't happen!/Unhandled */ + throw WrongType(); + break; + } +} + +void Value::set_hex(std::string const& in) { + istringstream input(in); + input.flags(ios::hex); + int result = 0; + input >> result; + _hex = result; +} + +void Value::set_int(string const &in) { + istringstream input(in); + int result = 0; + input >> result; + _int = result; +} +void Value::set_double(string const &in) { + istringstream input(in); + double result = 0; + input >> result; + _double = result; +} + +void Value::set_bool(string const &in) { + istringstream input(in); + string result; + input >> result; + _bool = true; + lowcase(result); + /* valid false entries: 0 ,d*, f*, off everything else gets true */ + if( !result.size() ) return; + if(result[0] == '0' || result[0] == 'd' || result[0] == 'f' || result == "off") + _bool = false; +} + +void Value::set_string(string const & in) { + if(!_string) _string = new string(); + _string->assign(in); +} + +string Value::ToString() const { + ostringstream oss; + switch(type) { + case V_HEX: + oss.flags(ios::hex); + oss << _hex; + break; + case V_INT: + oss << _int; + break; + case V_BOOL: + oss << boolalpha << _bool; + break; + case V_STRING: + oss << *_string; + break; + case V_DOUBLE: + oss.precision(2); + oss << fixed << _double; + break; + case V_NONE: + case V_CURRENT: + default: + E_Exit("ToString messed up ?"); + break; + } + return oss.str(); +} bool Property::CheckValue(Value const& in, bool warn){ - if(suggested_values.empty()) return false; + if(suggested_values.empty()) return true; for(iter it = suggested_values.begin();it != suggested_values.end();it++) { if ( (*it) == in) { //Match! return true; } } - if(warn) LOG_MSG("Value not in suggested values"); + if(warn) LOG_MSG("\"%s\" is not a valid value for variable: %s.\nIt might now be reset it to default value: %s",in.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); return false; } +void Property::Set_help(string const& in) { + string result = string("CONFIG_") + propname; + upcase(result); + MSG_Add(result.c_str(),in.c_str()); +} + +char const* Property::Get_help() { + string result = string("CONFIG_") + propname; + upcase(result); + return MSG_Get(result.c_str()); +} + + bool Prop_int::CheckValue(Value const& in, bool warn) { - if(Property::CheckValue(in,warn)) return true; + if(suggested_values.empty() && Property::CheckValue(in,warn)) return true; //No >= and <= in Value type and == is ambigious int mi = min; int ma = max; int va = static_cast(Value(in)); if(mi == -1 && ma == -1) return true; if (va >= mi && va <= ma) return true; - if(warn) LOG_MSG("Value not included in range"); + if(warn) LOG_MSG("%s lies outside the range %s-%s for variable: %s.\nIt might now be reset to the default value: %s",in.ToString().c_str(),min.ToString().c_str(),max.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); return false; } -void Prop_double::SetValue(char* input){ - input=trim(input); - value = static_cast(atof(input)); +void Prop_double::SetValue(std::string const& input){ + Value val(input,Value::V_DOUBLE); + SetVal(val,false,true); } -void Prop_int::SetValue(char* input){ - input=trim(input); - value = atoi(input); +//void Property::SetValue(char* input){ +// value.SetValue(input, Value::V_CURRENT); +//} +void Prop_int::SetValue(std::string const& input){; + Value val(input,Value::V_INT); + SetVal(val,false,true); } -void Prop_string::SetValue(char* input){ - input=trim(input); - value=input; +void Prop_string::SetValue(std::string const& input){ + Value val(input,Value::V_STRING); + SetVal(val,false,true); } -void Prop_bool::SetValue(char* input){ - input=lowcase(trim(input)); - /* valid false entries: 0 ,d*, of* ,f* everything else gets true */ - if((input[0]=='0') || (input[0]=='d') || ( (input[0]=='o') && (input[1]=='f')) || (input[0]=='f')){ - value._bool=false; - }else{ - value._bool=true; +void Prop_bool::SetValue(std::string const& input){ + value.SetValue(input,Value::V_BOOL); +} + +void Prop_hex::SetValue(std::string const& input){ + Value val(input,Value::V_HEX); + SetVal(val,false,true); +} + +//TODO checkvalue stuff +void Prop_multival::SetValue(std::string const& input) { + Value val(input,Value::V_STRING); + SetVal(val,false,true); + + std::string local(input); + int i = 0; + Property *p = section->Get_prop(0); + //No properties in this section. do nothing + if(!p) return; + string::size_type loc = string::npos; + while( (p = section->Get_prop(i++)) ) { + //trim leading seperators + loc = local.find_first_not_of(seperator); + if(loc != string::npos) local.erase(0,loc); + loc = local.find_first_of(seperator); + string in = "";//default value + if(loc != string::npos) { //seperator found + in = local.substr(0,loc); + local.erase(0,loc+1); + } else if(local.size()) { //last argument + in = local; + local = ""; + } + p->SetValue(in); } } -void Prop_hex::SetValue(char* input){ - input=trim(input); - if(!sscanf(input,"%X",&(value._hex))) value._hex=0; -} - -void Prop_int::GetValuestring(char* str) const{ - sprintf(str,"%d",value._int); -} - -void Prop_string::GetValuestring(char* str) const{ - sprintf(str,"%s",value._string->c_str()); -} - -void Prop_bool::GetValuestring(char* str) const{ - sprintf(str,"%s",value._bool?"true":"false"); -} - -void Prop_double::GetValuestring(char* str) const { - sprintf(str,"%1.2f",value._double); -} - -void Prop_hex::GetValuestring(char* str) const { - sprintf(str,"%X",value._hex); -} +/* void Section_prop::Add_double(char const * const _propname, double _value) { Property* test=new Prop_double(_propname,_value); properties.push_back(test); +}*/ + +void Property::Set_values(const char * const *in) { + Value::Etype type = default_value.type; + int i = 0; + while (in[i]) { + Value val(in[i],type); + suggested_values.push_back(val); + i++; + } +} + +Prop_int* Section_prop::Add_int(string const& _propname, Property::Changeable::Value when, int _value) { + Prop_int* test=new Prop_int(_propname,when,_value); + properties.push_back(test); + return test; +} + +Prop_string* Section_prop::Add_string(string const& _propname, Property::Changeable::Value when, char const * const _value) { + Prop_string* test=new Prop_string(_propname,when,_value); + properties.push_back(test); + return test; +} + +Prop_bool* Section_prop::Add_bool(string const& _propname, Property::Changeable::Value when, bool _value) { + Prop_bool* test=new Prop_bool(_propname,when,_value); + properties.push_back(test); + return test; +} +Prop_hex* Section_prop::Add_hex(string const& _propname, Property::Changeable::Value when, Hex _value) { + Prop_hex* test=new Prop_hex(_propname,when,_value); + properties.push_back(test); + return test; +} +Prop_multival* Section_prop::Add_multi(std::string const& _propname, Property::Changeable::Value when,std::string const& sep) { + Prop_multival* test = new Prop_multival(_propname,when,sep); + properties.push_back(test); + return test; } -Prop_int& Section_prop::Add_int(const char* _propname, int _value) { - Prop_int* test=new Prop_int(_propname,_value); - properties.push_back(test); - return *test; -} - -Prop_string& Section_prop::Add_string(char const * const _propname, char const * const _value) { - Prop_string* test=new Prop_string(_propname,_value); - properties.push_back(test); - return *test; -} - -Prop_bool& Section_prop::Add_bool(char const * const _propname, bool _value) { - Prop_bool* test=new Prop_bool(_propname,_value); - properties.push_back(test); - return *test; -} -Prop_hex& Section_prop::Add_hex(const char* _propname, int _value) { - Prop_hex* test=new Prop_hex(_propname,_value); - properties.push_back(test); - return *test; -} -int Section_prop::Get_int(char const * const _propname) const { +int Section_prop::Get_int(string const&_propname) const { for(const_it tel=properties.begin();tel!=properties.end();tel++){ if((*tel)->propname==_propname){ return ((*tel)->GetValue()); @@ -212,7 +350,7 @@ int Section_prop::Get_int(char const * const _propname) const { return 0; } -bool Section_prop::Get_bool(char const * const _propname) const { +bool Section_prop::Get_bool(string const& _propname) const { for(const_it tel=properties.begin();tel!=properties.end();tel++){ if((*tel)->propname==_propname){ return ((*tel)->GetValue()); @@ -220,13 +358,22 @@ bool Section_prop::Get_bool(char const * const _propname) const { } return false; } -double Section_prop::Get_double(char const * const _propname) const { +double Section_prop::Get_double(string const& _propname) const { for(const_it tel=properties.begin();tel!=properties.end();tel++){ if((*tel)->propname==_propname){ return ((*tel)->GetValue()); } } - return false; + return 0.0; +} +Prop_multival* Section_prop::Get_multival(string const& _propname) const { + for(const_it tel=properties.begin();tel!=properties.end();tel++){ + if((*tel)->propname==_propname){ + Prop_multival* val = dynamic_cast((*tel)); + if(val) return val; else return NULL; + } + } + return NULL; } Property* Section_prop::Get_prop(int index){ @@ -236,7 +383,7 @@ Property* Section_prop::Get_prop(int index){ return NULL; } -const char* Section_prop::Get_string(char const * const _propname) const { +const char* Section_prop::Get_string(string const& _propname) const { for(const_it tel=properties.begin();tel!=properties.end();tel++){ if((*tel)->propname==_propname){ return ((*tel)->GetValue()); @@ -244,50 +391,57 @@ const char* Section_prop::Get_string(char const * const _propname) const { } return ""; } -int Section_prop::Get_hex(char const * const _propname) const { +Hex Section_prop::Get_hex(string const& _propname) const { for(const_it tel=properties.begin();tel!=properties.end();tel++){ if((*tel)->propname==_propname){ - return ((*tel)->GetValue())._hex; + return ((*tel)->GetValue()); } } return 0; } -void Section_prop::HandleInputline(char *gegevens){ - char * rest=strrchr(gegevens,'='); - if(!rest) return; - *rest = 0; - gegevens=trim(gegevens); +void trim(string& in) { + string::size_type loc = in.find_first_not_of(' '); + if(loc != string::npos) in.erase(0,loc); + loc = in.find_last_not_of(' '); + if(loc != string::npos) in.erase(loc+1); +} + +//TODO double c_str +void Section_prop::HandleInputline(string const& gegevens){ + string str1 = gegevens; + string::size_type loc = str1.find('='); + if(loc == string::npos) return; + string name = str1.substr(0,loc); + string val = str1.substr(loc + 1); + /* trim the results incase there were spaces somewhere */ + trim(name);trim(val); for(it tel=properties.begin();tel!=properties.end();tel++){ - if(!strcasecmp((*tel)->propname.c_str(),gegevens)){ - (*tel)->SetValue(rest+1); + if(!strcasecmp((*tel)->propname.c_str(),name.c_str())){ + (*tel)->SetValue(val); return; } } } - void Section_prop::PrintData(FILE* outfile) const { - char temp[1000]; /* Should be enough for the properties */ /* Now print out the individual section entries */ for(const_it tel=properties.begin();tel!=properties.end();tel++){ - (*tel)->GetValuestring(temp); - fprintf(outfile,"%s=%s\n",(*tel)->propname.c_str(),temp); + fprintf(outfile,"%s=%s\n",(*tel)->propname.c_str(),(*tel)->GetValue().ToString().c_str()); } } -static char buffer[1024]; -char const * Section_prop::GetPropValue(char const * const _property) const{ +//TODO geen noodzaak voor 2 keer c_str +string Section_prop::GetPropValue(string const& _property) const{ for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if(!strcasecmp((*tel)->propname.c_str(),_property)){ - (*tel)->GetValuestring(buffer); - return buffer; + if(!strcasecmp((*tel)->propname.c_str(),_property.c_str())){ + return (*tel)->GetValue().ToString(); } } - return NULL; + return NO_SUCH_PROPERTY; } -void Section_line::HandleInputline(char* line){ +void Section_line::HandleInputline(string const& line){ data+=line; data+="\n"; } @@ -296,8 +450,8 @@ void Section_line::PrintData(FILE* outfile) const { fprintf(outfile,"%s",data.c_str()); } -char const* Section_line::GetPropValue(char const * const /* _property*/) const { - return NULL; +string Section_line::GetPropValue(string const& /* _property*/) const { + return NO_SUCH_PROPERTY; } void Config::PrintConfig(char const * const configfilename) const { @@ -403,17 +557,17 @@ Section* Config::GetSection(int index){ } return NULL; } - -Section* Config::GetSection(char const * const _sectionname) const{ +//c_str() 2x +Section* Config::GetSection(string const& _sectionname) const{ for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - if (!strcasecmp((*tel)->GetName(),_sectionname)) return (*tel); + if (!strcasecmp((*tel)->GetName(),_sectionname.c_str())) return (*tel); } return NULL; } Section* Config::GetSectionFromProperty(char const * const prop) const{ for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - if ((*tel)->GetPropValue(prop)) return (*tel); + if ((*tel)->GetPropValue(prop) != NO_SUCH_PROPERTY) return (*tel); } return NULL; } @@ -425,27 +579,17 @@ bool Config::ParseConfigFile(char const * const configfilename){ const char * settings_type = first_configfile?"primary":"additional"; first_configfile = false; LOG_MSG("CONFIG:Loading %s settings from config file %s", settings_type,configfilename); - char gegevens[1024]; + string gegevens; Section* currentsection = NULL; Section* testsec = NULL; while (in) { - in.getline(gegevens,1024); - char* temp; - char* s; - int len; - s = gegevens; + getline(in,gegevens); - /* strip trailing whitespace */ - for (len = strlen(s); len > 0 && isspace(s[len - 1]); len--) { - /* nothing */ - } - s[len] = 0; + /* strip leading/trailing whitespace */ + trim(gegevens); + if(!gegevens.size()) continue; - /* strip leading whitespace */ - while (isspace(s[0])) { - s++; - } - switch(s[0]){ + switch(gegevens[0]){ case '%': case '\0': case '#': @@ -454,16 +598,19 @@ bool Config::ParseConfigFile(char const * const configfilename){ continue; break; case '[': - temp = strrchr(s,']'); - *temp=0; - testsec = GetSection(&s[1]); + { + string::size_type loc = gegevens.find(']'); + if(loc == string::npos) continue; + gegevens.erase(loc); + testsec = GetSection(gegevens.substr(1)); if(testsec != NULL ) currentsection = testsec; testsec = NULL; + } break; default: - try{ - if(currentsection) currentsection->HandleInputline(s); - }catch(const char* message){ + try { + if(currentsection) currentsection->HandleInputline(gegevens); + } catch(const char* message) { message=0; //EXIT with message } diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 4b3a1307..6dba9d7a 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_cmds.cpp,v 1.80 2008-01-19 11:02:29 qbix79 Exp $ */ +/* $Id: shell_cmds.cpp,v 1.81 2008-02-10 11:14:03 qbix79 Exp $ */ #include "dosbox.h" #include "shell.h" @@ -74,8 +74,8 @@ bool DOS_Shell::CheckConfig(char* cmd_in,char*line) { Section* test = control->GetSectionFromProperty(cmd_in); if(!test) return false; if(line && !line[0]) { - char const* val = test->GetPropValue(cmd_in); - if(val) WriteOut("%s\n",val); + std::string val = test->GetPropValue(cmd_in); + if(val != NO_SUCH_PROPERTY) WriteOut("%s\n",val.c_str()); return true; } char newcom[1024]; newcom[0] = 0; strcpy(newcom,"z:\\config ");