OSDN Git Service

[General][Qt] Merge updtream 2016-03-05 (1).FTBFSs exist yet.
[csp-qt/common_source_project-fm7.git] / source / src / common.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2013.01.17-
6
7         [ common ]
8 */
9 #if defined(_USE_QT)
10 #include <string.h>
11 #include <fcntl.h>
12 #if !defined(__WIN32) && !defined(__WIN64)
13 #include <unistd.h>
14 #else
15 #include <io.h>
16 #include <direct.h>
17 #endif
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21
22 #include "agar_logger.h"
23
24 #include <string>
25 #include <algorithm>
26 #include <cctype>
27
28 #elif defined(_WIN32)
29 #include <shlwapi.h>
30 #pragma comment(lib, "shlwapi.lib")
31 #else
32 #include <time.h>
33 #endif
34
35 #include <math.h>
36 #include "common.h"
37 #include "config.h"
38
39 #if defined(__MINGW32__) || defined(__MINGW64__)
40 extern DWORD GetLongPathName(LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer);
41 #endif
42  
43 uint32_t EndianToLittle_DWORD(uint32_t x)
44 {
45 #if defined(__LITTLE_ENDIAN__)
46         return x;
47 #else
48         uint32_t y;
49         y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
50             ((x & 0x00ff0000) >> 8)  | ((x & 0xff000000) >> 24);
51         return y;
52 #endif
53 }
54
55 uint16_t EndianToLittle_WORD(uint16_t x)
56 {
57 #if defined(__LITTLE_ENDIAN__)
58         return x;
59 #else
60         uint16_t y;
61         y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
62         return y;
63 #endif
64 }
65
66 #ifndef _MSC_VER
67 int max(int a, int b)
68 {
69         if(a > b) {
70                 return a;
71         } else {
72                 return b;
73         }
74 }
75
76 unsigned int max(unsigned int a, unsigned int b)
77 {
78         if(a > b) {
79                 return a;
80         } else {
81                 return b;
82         }
83 }
84
85 int min(int a, int b)
86 {
87         if(a < b) {
88                 return a;
89         } else {
90                 return b;
91         }
92 }
93
94 unsigned int min(unsigned int a, unsigned int b)
95 {
96         if(a < b) {
97                 return a;
98         } else {
99                 return b;
100         }
101 }
102 #endif
103
104
105 #ifndef SUPPORT_SECURE_FUNCTIONS
106 //errno_t my_tfopen_s(FILE** pFile, const _TCHAR *filename, const _TCHAR *mode)
107 //{
108 //      if((*pFile = _tfopen(filename, mode)) != NULL) {
109 //              return 0;
110 //      } else {
111 //              return errno;
112 //      }
113 //}
114
115 errno_t my_strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource)
116 {
117         strcpy(strDestination, strSource);
118         return 0;
119 }
120
121 errno_t my_tcscpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
122 {
123         _tcscpy(strDestination, strSource);
124         return 0;
125 }
126
127 errno_t my_strncpy_s(char *strDestination, size_t numberOfElements, const char *strSource, size_t count)
128 {
129         strncpy(strDestination, strSource, count);
130         return 0;
131 }
132
133 errno_t my_tcsncpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource, size_t count)
134 {
135         _tcsncpy(strDestination, strSource, count);
136         return 0;
137 }
138
139 char *my_strtok_s(char *strToken, const char *strDelimit, char **context)
140 {
141         return strtok(strToken, strDelimit);
142 }
143
144 _TCHAR *my_tcstok_s(_TCHAR *strToken, const char *strDelimit, _TCHAR **context)
145 {
146         return _tcstok(strToken, strDelimit);
147 }
148
149 int my_sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
150 {
151         va_list ap;
152         va_start(ap, format);
153         int result = vsprintf(buffer, format, ap);
154         va_end(ap);
155         return result;
156 }
157
158 int my_stprintf_s(_TCHAR *buffer, size_t sizeOfBuffer, const _TCHAR *format, ...)
159 {
160         va_list ap;
161         va_start(ap, format);
162         int result = _vstprintf(buffer, format, ap);
163         va_end(ap);
164         return result;
165 }
166
167 int my_vsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr)
168 {
169         return vsprintf(buffer, format, argptr);
170 }
171
172 int my_vstprintf_s(_TCHAR *buffer, size_t numberOfElements, const _TCHAR *format, va_list argptr)
173 {
174         return _vstprintf(buffer, format, argptr);
175 }
176 #endif
177
178  
179 #ifndef _WIN32
180 BOOL MyWritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName)
181 {
182         BOOL result = FALSE;
183         FILEIO* fio_i = new FILEIO();
184         if(fio_i->Fopen(lpFileName, FILEIO_READ_ASCII)) {
185                 char tmp_path[_MAX_PATH];
186                 my_sprintf_s(tmp_path, _MAX_PATH, "%s.$$$", lpFileName);
187                 FILEIO* fio_o = new FILEIO();
188                 if(fio_o->Fopen(tmp_path, FILEIO_WRITE_ASCII)) {
189                         bool in_section = false;
190                         char section[1024], line[1024], *equal;
191                         my_sprintf_s(section, 1024, "[%s]", lpAppName);
192                         while(fio_i->Fgets(line, 1024) != NULL && strlen(line) > 0) {
193                                 if(line[strlen(line) - 1] == '\n') {
194                                         line[strlen(line) - 1] = '\0';
195                                 }
196                                 if(!result) {
197                                         if(line[0] == '[') {
198                                                 if(in_section) {
199                                                         fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
200                                                         result = TRUE;
201                                                 } else if(strcmp(line, section) == 0) {
202                                                         in_section = true;
203                                                 }
204                                         } else if(in_section && (equal = strstr(line, "=")) != NULL) {
205                                                 *equal = '\0';
206                                                 if(strcmp(line, lpKeyName) == 0) {
207                                                         fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
208                                                         result = TRUE;
209                                                         continue;
210                                                 }
211                                                 *equal = '=';
212                                         }
213                                 }
214                                 fio_o->Fprintf("%s\n", line);
215                         }
216                         if(!result) {
217                                 if(!in_section) {
218                                         fio_o->Fprintf("[%s]\n", lpAppName);
219                                 }
220                                 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
221                                 result = TRUE;
222                         }
223                         fio_o->Fclose();
224                 }
225                 delete fio_o;
226                 fio_i->Fclose();
227                 if(result) {
228                         if(!(FILEIO::RemoveFile(lpFileName) && FILEIO::RenameFile(tmp_path, lpFileName))) {
229                                 result = FALSE;
230                         }
231                 }
232         } else {
233                 FILEIO* fio_o = new FILEIO();
234                 if(fio_o->Fopen(lpFileName, FILEIO_WRITE_ASCII)) {
235                         fio_o->Fprintf("[%s]\n", lpAppName);
236                         fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
237                         fio_o->Fclose();
238                 }
239                 delete fio_o;
240         }
241         delete fio_i;
242         return result;
243 }
244
245 static std::string MyGetPrivateProfileStr(const _TCHAR *lpAppName, const _TCHAR *lpKeyName, _TCHAR *lpFileName)
246 {
247    std::string key;
248    char ibuf[4096 + 102];
249    int64_t i;
250    int l_len;
251    int c = '\0';
252    std::string::size_type  pos;
253    std::string key_str;
254    std::string got_str;
255    FILEIO *pf = new FILEIO;
256    
257    key = lpAppName;
258    key = key + ".";
259    key = key + lpKeyName;
260    got_str = "";
261    if(pf->Fopen(lpFileName, FILEIO_READ_ASCII) != true) {
262            delete pf;
263            return got_str;
264    }
265    AGAR_DebugLog(AGAR_LOG_DEBUG, "Try App: %s Key: %s", lpAppName, lpKeyName);
266    pf->Fseek(0, FILEIO_SEEK_SET);
267    do {
268            key_str = key;
269            ibuf[0] = '\0';
270            i = 0;
271            l_len = 0;
272            while(1) {
273                    if(l_len > (4096 + 100)) { // Too long, read dummy.
274                            c = (char)pf->Fgetc();
275                            if((c != EOF) && (c != '\n') && (c != '\0')) continue;
276                            break;
277                    }
278                    c = (char)pf->Fgetc();
279                    if((c == EOF) || (c == '\n') || (c == '\0')) break;
280                    ibuf[i] = (char)c;
281                    i++;
282                    l_len++;
283            }
284            l_len = 0;
285            ibuf[i] = '\0';
286            got_str = ibuf;
287            key_str = key_str + "=";
288            pos = got_str.find(key_str);
289            if(pos != std::string::npos) break;
290            if(c == EOF) return "";
291    } while(c != EOF);
292    pf->Fclose();
293    delete pf;
294    
295    got_str.erase(0, pos + key_str.length());
296    AGAR_DebugLog(AGAR_LOG_DEBUG, "Got: %s Length: %d", got_str.c_str(), got_str.length());
297    return got_str;
298 }
299
300
301 DWORD MyGetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, _TCHAR *lpReturnedString, DWORD nSize, LPCTSTR lpFileName)
302 {
303         _TCHAR *lpp = (_TCHAR *)lpReturnedString;
304         if(lpDefault != NULL) {
305                 my_strcpy_s(lpp, nSize, lpDefault);
306         } else {
307                 lpp[0] = '\0';
308         }
309         FILEIO* fio = new FILEIO();
310         if(fio->Fopen(lpFileName, FILEIO_READ_ASCII)) {
311                 bool in_section = false;
312                 char section[1024], line[1024], *equal;
313                 my_sprintf_s(section, 1024, "[%s]", lpAppName);
314                 while(fio->Fgets(line, 1024) != NULL && strlen(line) > 0) {
315                         if(line[strlen(line) - 1] == '\n') {
316                                 line[strlen(line) - 1] = '\0';
317                         }
318                         if(line[0] == '[') {
319                                 if(in_section) {
320                                         break;
321                                 } else if(strcmp(line, section) == 0) {
322                                         in_section = true;
323                                 }
324                         } else if(in_section && (equal = strstr(line, "=")) != NULL) {
325                                 *equal = '\0';
326                                 if(strcmp(line, lpKeyName) == 0) {
327                                         my_strcpy_s(lpp, nSize, equal + 1);
328                                         break;
329                                 }
330                         }
331                 }
332                 fio->Fclose();
333         }
334         delete fio;
335         return strlen(lpp);
336 }
337
338 UINT MyGetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName)
339 {
340         // write your compatible function, if possible in standard C/C++ code
341         int i;
342         char sstr[128];
343         char sval[128];
344         std::string s;
345         memset(sstr, 0x00, sizeof(sstr));
346         memset(sval, 0x00, sizeof(sval));
347         snprintf(sval, 128, "%d", nDefault); 
348         MyGetPrivateProfileString(lpAppName,lpKeyName, sval, sstr, 128, lpFileName);
349         s = sstr;
350         
351         if(s.empty()) {
352                 i = nDefault;
353         } else {
354                 i = strtol(s.c_str(), NULL, 10);
355         }
356         //AGAR_DebugLog(AGAR_LOG_DEBUG, "Got Int: %d\n", i);
357         return i;
358 }
359 #endif
360
361 #if defined(_RGB555)
362 scrntype_t RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
363 {
364         scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
365         scrntype_t gg = ((scrntype_t)g * 0x1f) / 0xff;
366         scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
367         return (rr << 10) | (gg << 5) | bb;
368 }
369
370 scrntype_t RGBA_COLOR(uint32_t r, uint32_t g, uint b, uint32_t a)
371 {
372         return RGB_COLOR(r, g, b);
373 }
374
375 uint8_t R_OF_COLOR(scrntype_t c)
376 {
377         c = (c >> 10) & 0x1f;
378         c = (c * 0xff) / 0x1f;
379         return (uint8_t)c;
380 }
381
382 uint8_t G_OF_COLOR(scrntype_t c)
383 {
384         c = (c >>  5) & 0x1f;
385         c = (c * 0xff) / 0x1f;
386         return (uint8_t)c;
387 }
388
389 uint8_t B_OF_COLOR(scrntype_t c)
390 {
391         c = (c >>  0) & 0x1f;
392         c = (c * 0xff) / 0x1f;
393         return (uint8_t)c;
394 }
395
396 uint8_t A_OF_COLOR(scrntype_t c)
397 {
398         return 0;
399 }
400 #elif defined(_RGB565)
401 scrntype_t RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
402 {
403         scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
404         scrntype_t gg = ((scrntype_t)g * 0x3f) / 0xff;
405         scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
406         return (rr << 11) | (gg << 5) | bb;
407 }
408
409 scrntype_t RGBA_COLOR(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
410 {
411         return RGB_COLOR(r, g, b);
412 }
413
414 uint8_t R_OF_COLOR(scrntype_t c)
415 {
416         c = (c >> 11) & 0x1f;
417         c = (c * 0xff) / 0x1f;
418         return (uint8_t)c;
419 }
420
421 uint8_t G_OF_COLOR(scrntype_t c)
422 {
423         c = (c >>  5) & 0x3f;
424         c = (c * 0xff) / 0x3f;
425         return (uint8_t)c;
426 }
427
428 uint8_t B_OF_COLOR(scrntype_t c)
429 {
430         c = (c >>  0) & 0x1f;
431         c = (c * 0xff) / 0x1f;
432         return (uint8_t)c;
433 }
434
435 uint8_t A_OF_COLOR(scrntype_t c)
436 {
437         return 0;
438 }
439 #endif
440
441
442 #include "fileio.h"
443 struct to_upper {  // Refer from documentation of libstdc++, GCC5.
444         char operator() (char c) const { return std::toupper(c); }
445 };
446
447 #if defined(_USE_QT)
448 extern std::string cpp_homedir;
449 extern std::string my_procname;
450 #include <QDir>
451 #endif
452
453 const _TCHAR *get_application_path()
454 {
455         static _TCHAR app_path[_MAX_PATH];
456         static bool initialized = false;
457         
458         if(!initialized) {
459 #ifdef _MSC_VER
460                 _TCHAR tmp_path[_MAX_PATH], *ptr = NULL;
461                 if(GetModuleFileName(NULL, tmp_path, _MAX_PATH) != 0 && GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr) != 0 && ptr != NULL) {
462                         *ptr = _T('\0');
463                 } else {
464                         my_tcscpy_s(app_path, _MAX_PATH, _T(".\\"));
465                 }
466 #else
467         #if defined(Q_OS_WIN)
468                 std::string delim = "\\";
469         #else
470                 std::string delim = "/";
471         #endif
472                 std::string cpath = cpp_homedir + my_procname + delim;
473                 strncpy(app_path, cpath.c_str(), _MAX_PATH);
474                 {
475                         struct stat st;
476 #if !defined(__WIN32) && !defined(__WIN64)
477                         if(fstatat(AT_FDCWD, app_path, &st, 0) != 0) {
478                                 mkdirat(AT_FDCWD, app_path, 0700); // Not found
479                         }
480 #else // __WIN32
481 # if defined(_USE_QT)
482                         if(stat(app_path, &st) != 0) {
483                                 QDir dir = QDir::current();
484                                 dir.mkdir(QString::fromUtf8(app_path));
485                         }
486 # else
487                         if(stat(app_path, &st) != 0) {
488                                 _mkdir(app_path); // Not found
489                         }
490 # endif
491 #endif             
492                 }
493 #endif
494                 
495                 initialized = true;
496         }
497         return (const _TCHAR *)app_path;
498 }
499
500 const _TCHAR *create_local_path(const _TCHAR *format, ...)
501 {
502         static _TCHAR file_path[8][_MAX_PATH];
503         static unsigned int table_index = 0;
504         unsigned int output_index = (table_index++) & 7;
505         _TCHAR file_name[_MAX_PATH];
506         va_list ap;
507         
508         va_start(ap, format);
509         my_vstprintf_s(file_name, _MAX_PATH, format, ap);
510         va_end(ap);
511         my_stprintf_s(file_path[output_index], _MAX_PATH, _T("%s%s"), get_application_path(), file_name);       
512         return (const _TCHAR *)file_path[output_index];
513 }
514
515 void create_local_path(_TCHAR *file_path, int length, const _TCHAR *format, ...)
516 {
517         _TCHAR file_name[_MAX_PATH];
518         va_list ap;
519         
520         va_start(ap, format);
521         my_vstprintf_s(file_name, _MAX_PATH, format, ap);
522         va_end(ap);
523         my_stprintf_s(file_path, length, _T("%s%s"), get_application_path(), file_name);
524 }
525
526 const _TCHAR *create_date_file_path(const _TCHAR *extension)
527 {
528         cur_time_t cur_time;
529         
530         get_host_time(&cur_time);
531         return create_local_path(_T("%d-%0.2d-%0.2d_%0.2d-%0.2d-%0.2d.%s"), cur_time.year, cur_time.month, cur_time.day, cur_time.hour, cur_time.minute, cur_time.second, extension);
532 }
533
534 void create_date_file_path(_TCHAR *file_path, int length, const _TCHAR *extension)
535 {
536         my_tcscpy_s(file_path, length, create_date_file_path(extension));
537 }
538
539 bool check_file_extension(const _TCHAR *file_path, const _TCHAR *ext)
540 {
541 #if defined(_USE_QT)
542         std::string s_fpath = file_path;
543         std::string s_ext = ext;
544         bool f = false;
545         int pos;
546         std::transform(s_fpath.begin(), s_fpath.end(), s_fpath.begin(), to_upper());
547         std::transform(s_ext.begin(), s_ext.end(), s_ext.begin(), to_upper());
548         if(s_fpath.length() < s_ext.length()) return false;
549         pos = s_fpath.rfind(s_ext.c_str(), s_fpath.length());
550         if((pos != std::string::npos) && (pos >= (s_fpath.length() - s_ext.length()))) return true; 
551         return false;
552 #else
553         int nam_len = _tcslen(file_path);
554         int ext_len = _tcslen(ext);
555         
556         return (nam_len >= ext_len && _tcsncicmp(&file_path[nam_len - ext_len], ext, ext_len) == 0);
557 #endif
558 }
559
560 const _TCHAR *get_file_path_without_extensiton(const _TCHAR *file_path)
561 {
562         static _TCHAR path[8][_MAX_PATH];
563         static unsigned int table_index = 0;
564         unsigned int output_index = (table_index++) & 7;
565         
566         my_tcscpy_s(path[output_index], _MAX_PATH, file_path);
567 #ifdef _MSC_VER
568         PathRemoveExtension(path[output_index]);
569 #else
570         _TCHAR *p = _tcsrchr(path[output_index], _T('.'));
571         if(p != NULL) {
572                 *p = _T('\0');
573         }
574 #endif
575         return (const _TCHAR *)path[output_index];
576 }
577
578 void get_long_full_path_name(const _TCHAR* src, _TCHAR* dst, size_t dst_len)
579 {
580         _TCHAR tmp[_MAX_PATH];
581         
582 #ifdef _WIN32
583         if(GetFullPathName(src, _MAX_PATH, tmp, NULL) == 0) {
584                 my_tcscpy_s(dst, dst_len, src);
585         } else if(GetLongPathName(tmp, dst, _MAX_PATH) == 0) {
586                 my_tcscpy_s(dst, dst_len, tmp);
587         }
588 #else
589         // write code for your environment
590 #endif
591 }
592
593 const _TCHAR* get_parent_dir(const _TCHAR* file)
594 {
595         static _TCHAR path[8][_MAX_PATH];
596         static unsigned int table_index = 0;
597         unsigned int output_index = (table_index++) & 7;
598         
599 #ifdef _WIN32
600         _TCHAR *ptr;
601         GetFullPathName(file, _MAX_PATH, path[output_index], &ptr);
602         if(ptr != NULL) {
603                 *ptr = _T('\0');
604         }
605 #else
606         // write code for your environment
607 #endif
608         return path[output_index];
609 }
610
611 const _TCHAR *create_string(const _TCHAR* format, ...)
612 {
613         static _TCHAR buffer[8][1024];
614         static unsigned int table_index = 0;
615         unsigned int output_index = (table_index++) & 7;
616         va_list ap;
617         
618         va_start(ap, format);
619         my_vstprintf_s(buffer[output_index], 1024, format, ap);
620         va_end(ap);
621         return (const _TCHAR *)buffer[output_index];
622 }
623
624 uint32_t get_crc32(uint8_t data[], int size)
625 {
626         static bool initialized = false;
627         static uint32_t table[256];
628         
629         if(!initialized) {
630                 for(int i = 0; i < 256; i++) {
631                         uint32_t c = i;
632                         for(int j = 0; j < 8; j++) {
633                                 if(c & 1) {
634                                         c = (c >> 1) ^ 0xedb88320;
635                                 } else {
636                                         c >>= 1;
637                                 }
638                         }
639                         table[i] = c;
640                 }
641                 initialized = true;
642         }
643         
644         uint32_t c = ~0;
645         for(int i = 0; i < size; i++) {
646                 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
647         }
648         return ~c;
649 }
650
651 uint16_t jis_to_sjis(uint16_t jis)
652 {
653         pair_t tmp;
654         
655         tmp.w.l = jis - 0x2121;
656         if(tmp.w.l & 0x100) {
657                 tmp.w.l += 0x9e;
658         } else {
659                 tmp.w.l += 0x40;
660         }
661         if(tmp.b.l > 0x7f) {
662                 tmp.w.l += 0x01;
663         }
664         tmp.b.h = (tmp.b.h >> 1) + 0x81;
665         if(tmp.w.l >= 0xa000) {
666                 tmp.w.l += 0x4000;
667         }
668         return tmp.w.l;
669 }
670
671 int decibel_to_volume(int decibel)
672 {
673         // +1 equals +0.5dB (same as fmgen)
674         return (int)(1024.0 * pow(10.0, decibel / 40.0) + 0.5);
675 }
676
677 int32_t apply_volume(int32_t sample, int volume)
678 {
679 //      int64_t output;
680         int32_t output;
681         if(sample < 0) {
682                 output = -sample;
683                 output *= volume;
684                 output >>= 10;
685                 output = -output;
686         } else {
687                 output = sample;
688                 output *= volume;
689                 output >>= 10;
690         }
691 //      if(output > 2147483647) {
692 //              return 2147483647;
693 //      } else if(output < (-2147483647 - 1)) {
694 //              return (-2147483647 - 1);
695 //      } else {
696 //              return (int32_t)output;
697 //      }
698         return output;
699 }
700
701 void get_host_time(cur_time_t* cur_time)
702 {
703 #ifdef _WIN32
704         SYSTEMTIME sTime;
705         GetLocalTime(&sTime);
706         cur_time->year = sTime.wYear;
707         cur_time->month = sTime.wMonth;
708         cur_time->day = sTime.wDay;
709         cur_time->day_of_week = sTime.wDayOfWeek;
710         cur_time->hour = sTime.wHour;
711         cur_time->minute = sTime.wMinute;
712         cur_time->second = sTime.wSecond;
713 #else
714         time_t timer = time(NULL);
715         struct tm *local = localtime(&timer);
716         cur_time->year = local->tm_year + 1900;
717         cur_time->month = local->tm_mon + 1;
718         cur_time->day = local->tm_mday;
719         cur_time->day_of_week = local->tm_wday;
720         cur_time->hour = local->tm_hour;
721         cur_time->minute = local->tm_min;
722         cur_time->second = local->tm_sec;
723 #endif
724 }
725
726 void cur_time_t::increment()
727 {
728         if(++second >= 60) {
729                 second = 0;
730                 if(++minute >= 60) {
731                         minute = 0;
732                         if(++hour >= 24) {
733                                 hour = 0;
734                                 // days in this month
735                                 int days = 31;
736                                 if(month == 2) {
737                                         days = LEAP_YEAR(year) ? 29 : 28;
738                                 } else if(month == 4 || month == 6 || month == 9 || month == 11) {
739                                         days = 30;
740                                 }
741                                 if(++day > days) {
742                                         day = 1;
743                                         if(++month > 12) {
744                                                 month = 1;
745                                                 year++;
746                                         }
747                                 }
748                                 if(++day_of_week >= 7) {
749                                         day_of_week = 0;
750                                 }
751                         }
752                 }
753         }
754 }
755
756 void cur_time_t::update_year()
757 {
758         // 1970-2069
759         if(year < 70) {
760                 year += 2000;
761         } else if(year < 100) {
762                 year += 1900;
763         }
764 }
765
766 void cur_time_t::update_day_of_week()
767 {
768         static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
769         int y = year - (month < 3);
770         day_of_week = (y + y / 4 - y / 100 + y / 400 + t[month - 1] + day) % 7;
771 }
772
773 #define STATE_VERSION   1
774
775 void cur_time_t::save_state(void *f)
776 {
777         FILEIO *state_fio = (FILEIO *)f;
778         
779         state_fio->FputUint32(STATE_VERSION);
780         
781         state_fio->FputInt32(year);
782         state_fio->FputInt32(month);
783         state_fio->FputInt32(day);
784         state_fio->FputInt32(day_of_week);
785         state_fio->FputInt32(hour);
786         state_fio->FputInt32(minute);
787         state_fio->FputInt32(second);
788         state_fio->FputBool(initialized);
789 }
790
791 bool cur_time_t::load_state(void *f)
792 {
793         FILEIO *state_fio = (FILEIO *)f;
794         
795         if(state_fio->FgetUint32() != STATE_VERSION) {
796                 return false;
797         }
798         year = state_fio->FgetInt32();
799         month = state_fio->FgetInt32();
800         day = state_fio->FgetInt32();
801         day_of_week = state_fio->FgetInt32();
802         hour = state_fio->FgetInt32();
803         minute = state_fio->FgetInt32();
804         second = state_fio->FgetInt32();
805         initialized = state_fio->FgetBool();
806         return true;
807 }
808