DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
include/dosbox.h
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #ifndef DOSBOX_DOSBOX_H
00021 #define DOSBOX_DOSBOX_H
00022 
00023 #include "config.h"
00024 #include "logging.h"
00025 
00026 #if defined(C_ICONV)
00027 /* good */
00028 #elif defined(C_ICONV_WIN32)
00029 /* good */
00030 #else
00031 /* auto-pick */
00032  #if defined(_WIN32) || defined(WINDOWS)
00033   #define C_ICONV_WIN32 1 /* use the Win32 API */
00034  #else
00035   #pragma warning "iconv backend not chosen, will become mandatory at some point"
00036  #endif
00037 #endif
00038 
00039 /* Mac OS X: There seems to be a problem with Macbooks where the touchpad
00040              is seen by SDL2 as a "touchscreen", even though the screen is
00041              not a touchscreen. The result is DOSBox-X getting mixed messages
00042              from both the mouse cursor and the touch pad, which makes the
00043              interface unusable. The solution is to ignore touch events on
00044              Mac OS X.
00045 
00046              Perhaps if DOSBox-X is someday ported to run on an iPad (with
00047              a touchscreen) this can be made conditional to allow touch
00048              events there. */
00049 #if defined(C_SDL2) && defined(MACOSX)
00050 # define IGNORE_TOUCHSCREEN
00051 #endif
00052 
00053 /* SANITY CHECK */
00054 #if defined(C_HEAVY_DEBUG) && !defined(C_DEBUG)
00055 # error If C_HEAVY_DEBUG is defined, then so must C_DEBUG
00056 #endif
00057 /* ------------ */
00058 
00059 #if defined(_MSC_VER)
00060 # include <sys/types.h>
00061 # include <sys/stat.h>
00062 
00063 /* Microsoft has their own stat/stat64 scheme */
00064 # define pref_stat                      _stati64
00065 # define pref_struct_stat       struct _stat64
00066 #else
00067 /* As long as FILE_OFFSET_BITS==64 Linux is quite good at allowing stat to work with 64-bit sizes */
00068 # define pref_stat                      stat
00069 # define pref_struct_stat       struct stat
00070 #endif
00071 
00072 // TODO: The autoconf script should test the size of long double
00073 #if defined(_MSC_VER)
00074 // Microsoft C++ sizeof(long double) == sizeof(double)
00075 #elif defined(__arm__)
00076 // ARMv7 (Raspberry Pi) does not have long double, sizeof(long double) == sizeof(double)
00077 #else
00078 // GCC, other compilers, have sizeof(long double) == 10 80-bit IEEE
00079 # define HAS_LONG_DOUBLE                1
00080 #endif
00081 
00082 GCC_ATTRIBUTE(noreturn) void            E_Exit(const char * format,...) GCC_ATTRIBUTE( __format__(__printf__, 1, 2));
00083 
00084 typedef Bits cpu_cycles_count_t;
00085 typedef Bitu cpu_cycles_countu_t;
00086 
00087 #include "clockdomain.h"
00088 
00089 class Config;
00090 class Section;
00091 
00092 #if defined(__GNUC__)
00093 # define DEPRECATED __attribute__((deprecated))
00094 #else
00095 # define DEPRECATED
00096 #endif
00097 
00098 enum MachineType {
00099         MCH_HERC,
00100         MCH_CGA,
00101         MCH_TANDY,
00102         MCH_PCJR,
00103         MCH_EGA,
00104         MCH_VGA,
00105         MCH_AMSTRAD,
00106         MCH_PC98,
00107 
00108     MCH_FM_TOWNS,                    // STUB!!
00109 
00110     MCH_MCGA,                        // IBM PS/2 model 30 Multi-Color Graphics Adapter
00111     MCH_MDA
00112 };
00113 
00114 enum SVGACards {
00115         SVGA_None,
00116         SVGA_S3Trio,
00117         SVGA_TsengET4K,
00118         SVGA_TsengET3K,
00119         SVGA_ParadisePVGA1A
00120 };
00121 
00122 typedef Bitu                            (LoopHandler)(void);
00123 
00124 extern Config*                          control;
00125 extern SVGACards                        svgaCard;
00126 extern MachineType                      machine;
00127 extern bool             SDLNetInited, uselfn;
00128 extern bool                             mono_cga;
00129 extern bool                             DEPRECATED mainline_compatible_mapping;
00130 extern bool                             DEPRECATED mainline_compatible_bios_mapping;
00131 
00132 #ifdef __SSE__
00133 extern bool                             sse1_available;
00134 extern bool                             sse2_available;
00135 #endif
00136 
00137 void                                    MSG_Add(const char*,const char*); //add messages to the internal languagefile
00138 const char*                             MSG_Get(char const *);     //get messages from the internal languagefile
00139 
00140 void                                    DOSBOX_RunMachine();
00141 void                                    DOSBOX_SetLoop(LoopHandler * handler);
00142 void                                    DOSBOX_SetNormalLoop();
00143 
00144 /* machine tests for use with if() statements */
00145 #define IS_TANDY_ARCH                   ((machine==MCH_TANDY) || (machine==MCH_PCJR))
00146 #define IS_EGAVGA_ARCH                  ((machine==MCH_EGA) || (machine==MCH_VGA))
00147 #define IS_EGA_ARCH             (machine==MCH_EGA)
00148 #define IS_VGA_ARCH             (machine==MCH_VGA)
00149 #define IS_PC98_ARCH            (machine==MCH_PC98)
00150 
00151 #define IS_FM_TOWNS             (machine==MCH_FM_TOWNS)
00152 
00153 /* machine tests for use with switch() statements */
00154 #define TANDY_ARCH_CASE                 MCH_TANDY: case MCH_PCJR
00155 #define EGAVGA_ARCH_CASE                MCH_EGA: case MCH_VGA
00156 #define VGA_ARCH_CASE                   MCH_VGA
00157 #define PC98_ARCH_CASE                  MCH_PC98
00158 
00159 #define FM_TOWNS_ARCH_CASE      MCH_FM_TOWNS
00160 
00161 #ifndef DOSBOX_LOGGING_H
00162 #include "logging.h"
00163 #endif // the logging system.
00164 
00165 extern ClockDomain                      clockdom_PCI_BCLK;
00166 extern ClockDomain                      clockdom_ISA_OSC;
00167 extern ClockDomain                      clockdom_ISA_BCLK;
00168 
00169 signed long long time_to_clockdom(ClockDomain &src,double t);
00170 unsigned long long update_clockdom_from_now(ClockDomain &dst);
00171 
00172 extern bool enable_pc98_jump;
00173 
00174 enum {
00175         UTF8ERR_INVALID=-1,
00176         UTF8ERR_NO_ROOM=-2
00177 };
00178 
00179 #ifndef UNICODE_BOM
00180 #define UNICODE_BOM 0xFEFF
00181 #endif
00182 
00183 int utf8_encode(char **ptr,const char *fence,uint32_t code);
00184 int utf8_decode(const char **ptr,const char *fence);
00185 int utf16le_encode(char **ptr,const char *fence,uint32_t code);
00186 int utf16le_decode(const char **ptr,const char *fence);
00187 
00188 typedef char utf8_t;
00189 typedef uint16_t utf16_t;
00190 
00191 /* for DOS filename handling we want a toupper that uses the MS-DOS code page within not the locale of the host */
00192 int ascii_toupper(int c);
00193 
00194 enum {
00195     BOOTHAX_NONE=0,
00196     BOOTHAX_MSDOS
00197 };
00198 
00199 extern Bit32u guest_msdos_LoL;
00200 extern Bit16u guest_msdos_mcb_chain;
00201 extern int boothax;
00202 
00203 /* C++11 user-defined literal, to help with byte units */
00204 typedef unsigned long long bytecount_t;
00205 
00206 static inline constexpr bytecount_t operator "" _bytes(const bytecount_t x) {
00207     return x;
00208 }
00209 
00210 static inline constexpr bytecount_t operator "" _parabytes(const bytecount_t x) { /* AKA bytes per segment increment in real mode */
00211     return x << bytecount_t(4u);
00212 }
00213 
00214 static inline constexpr bytecount_t operator "" _kibibytes(const bytecount_t x) {
00215     return x << bytecount_t(10u);
00216 }
00217 
00218 static inline constexpr bytecount_t operator "" _pagebytes(const bytecount_t x) { /* bytes per 4KB page in protected mode */
00219     return x << bytecount_t(12u);
00220 }
00221 
00222 static inline constexpr bytecount_t operator "" _mibibytes(const bytecount_t x) {
00223     return x << bytecount_t(20u);
00224 }
00225 
00226 static inline constexpr bytecount_t operator "" _gibibytes(const bytecount_t x) {
00227     return x << bytecount_t(30u);
00228 }
00229 
00230 static inline constexpr bytecount_t operator "" _tebibytes(const bytecount_t x) {
00231     return x << bytecount_t(40u);
00232 }
00233 
00234 /* and the same, for variables */
00235 
00236 static inline constexpr bytecount_t _bytes(const bytecount_t x) {
00237     return x;
00238 }
00239 
00240 static inline constexpr bytecount_t _parabytes(const bytecount_t x) { /* AKA bytes per segment increment in real mode */
00241     return x << bytecount_t(4u);
00242 }
00243 
00244 static inline constexpr bytecount_t _kibibytes(const bytecount_t x) {
00245     return x << bytecount_t(10u);
00246 }
00247 
00248 static inline constexpr bytecount_t _pagebytes(const bytecount_t x) { /* bytes per 4KB page in protected mode */
00249     return x << bytecount_t(12u);
00250 }
00251 
00252 static inline constexpr bytecount_t _mibibytes(const bytecount_t x) {
00253     return x << bytecount_t(20u);
00254 }
00255 
00256 static inline constexpr bytecount_t _gibibytes(const bytecount_t x) {
00257     return x << bytecount_t(30u);
00258 }
00259 
00260 static inline constexpr bytecount_t _tebibytes(const bytecount_t x) {
00261     return x << bytecount_t(40u);
00262 }
00263 
00264 #endif /* DOSBOX_DOSBOX_H */
00265 
00266 #ifndef SAVE_STATE_H_INCLUDED
00267 #define SAVE_STATE_H_INCLUDED
00268 
00269 #include <sstream>
00270 #include <map>
00271 #include <algorithm>
00272 #include <functional>
00273 #include <vector>
00274 
00275 
00276 #define WRITE_POD(x,y) \
00277         stream.write(reinterpret_cast<const char*>( (x) ), sizeof( (y) ) );
00278 
00279 #define WRITE_POD_SIZE(x,y) \
00280         stream.write(reinterpret_cast<const char*>( (x) ), (y) );
00281 
00282 #define READ_POD(x,y) \
00283         stream.read(reinterpret_cast<char*>( (x) ), sizeof( (y) ) );
00284 
00285 #define READ_POD_SIZE(x,y) \
00286         stream.read(reinterpret_cast<char*>( (x) ), (y) );
00287 
00288 
00289 
00290 class SaveState
00291 {
00292 public:
00293     static SaveState& instance();
00294 
00295    typedef std::string Error;
00296     static const size_t SLOT_COUNT = 10; //slot: [0,...,SLOT_COUNT - 1]
00297 
00298     void save   (size_t slot);       //throw (Error)
00299     void load   (size_t slot) const; //throw (Error)
00300     bool isEmpty(size_t slot) const;
00301     std::string getName(size_t slot) const;
00302 
00303     //initialization: register relevant components on program startup
00304     struct Component
00305     {
00306         virtual void getBytes(std::ostream& stream) = 0;
00307         virtual void setBytes(std::istream& stream) = 0;
00308     };
00309 
00310     void registerComponent(const std::string& uniqueName, Component& comp); //comp must have global lifetime!
00311 
00312 private:
00313     SaveState() {}
00314     SaveState(const SaveState&);
00315     SaveState& operator=(const SaveState&);
00316 
00317     class RawBytes
00318     {
00319     public:
00320         RawBytes() : dataExists(false), isCompressed(false) {}
00321         void set(const std::string& stream);
00322         std::string get() const; //throw (Error)
00323         void compress() const;   //throw (Error)
00324         bool dataAvailable() const;
00325     private:
00326         bool dataExists; //determine whether set method (even with empty string) was called
00327         mutable bool isCompressed; //design for logical not binary const
00328         mutable std::string bytes; //
00329     };
00330 
00331     struct CompData
00332     {
00333         CompData(Component& cmp) : comp(cmp), rawBytes(SLOT_COUNT) {}
00334         Component& comp;
00335         std::vector<RawBytes> rawBytes;
00336     };
00337 
00338     typedef std::map<std::string, CompData> CompEntry;
00339     CompEntry components;
00340 };
00341 
00342 
00343 //some helper functions
00344 template <class T>
00345 void writePOD(std::ostream& stream, const T& data);
00346 
00347 template <class T>
00348 void readPOD(std::istream& stream, T& data);
00349 
00350 void writeString(std::ostream& stream, const std::string& data);
00351 void readString(std::istream& stream, std::string& data);
00352 
00353 
00354 //Implementation of SaveState::Component for saving POD types only
00355 class SerializeGlobalPOD : public SaveState::Component
00356 {
00357 public:
00358     SerializeGlobalPOD(const std::string& compName)
00359     {
00360         SaveState::instance().registerComponent(compName, *this);
00361     }
00362 
00363     template <class T>
00364     void registerPOD(T& pod) //register POD for serializatioin
00365     {
00366         podRef.push_back(POD(pod));
00367     }
00368 
00369 protected:
00370     virtual void getBytes(std::ostream& stream)
00371     {
00372         std::for_each(podRef.begin(), podRef.end(), std::bind1st(WriteGlobalPOD(), &stream));
00373     }
00374 
00375     virtual void setBytes(std::istream& stream)
00376     {
00377         std::for_each(podRef.begin(), podRef.end(), std::bind1st(ReadGlobalPOD(), &stream));
00378     }
00379 
00380 private:
00381     struct POD
00382     {
00383         template <class T>
00384         POD(T& pod) : address(&pod), size(sizeof(T)) {}
00385         void* address;
00386         size_t size;
00387     };
00388 
00389     struct WriteGlobalPOD : public std::binary_function<std::ostream*, POD, void>
00390     {
00391         void operator()(std::ostream* stream, const POD& data) const
00392         {
00393             stream->write(static_cast<const char*>(data.address), data.size);
00394         }
00395     };
00396 
00397     struct ReadGlobalPOD : public std::binary_function<std::istream*, POD, void>
00398     {
00399         void operator()(std::istream* stream, const POD& data) const
00400         {
00401             stream->read(static_cast<char*>(data.address), data.size);
00402         }
00403     };
00404 
00405     std::vector<POD> podRef;
00406 };
00407 
00408 //---------------- inline implementation -------------------------
00409 template <class T>
00410 inline
00411 void writePOD(std::ostream& stream, const T& data)
00412 {
00413     stream.write(reinterpret_cast<const char*>(&data), sizeof(T));
00414 }
00415 
00416 
00417 template <class T>
00418 inline
00419 void readPOD(std::istream& stream, T& data)
00420 {
00421     stream.read(reinterpret_cast<char*>(&data), sizeof(T));
00422 }
00423 
00424 
00425 inline
00426 void writeString(std::ostream& stream, const std::string& data)
00427 {
00428     const size_t stringSize = data.size();
00429     writePOD(stream, stringSize);
00430     stream.write(data.c_str(), stringSize * sizeof(std::string::value_type));
00431 }
00432 
00433 
00434 inline
00435 void readString(std::istream& stream, std::string& data)
00436 {
00437     size_t stringSize = 0;
00438     readPOD(stream, stringSize);
00439     data.resize(stringSize);
00440     stream.read(&data[0], stringSize * sizeof(std::string::value_type));
00441 }
00442 #endif //SAVE_STATE_H_INCLUDED