OSDN Git Service

[UI][Qt] Implement new feature of upstream 2018-12-28.
[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
10 #if defined(_USE_QT)
11         #include <string.h>
12         #include <fcntl.h>
13         #if !defined(__WIN32) && !defined(__WIN64)
14                 #include <unistd.h>
15         #else
16                 #include <io.h>
17                 #include <direct.h>
18         #endif
19         #include <sys/types.h>
20         #include <sys/stat.h>
21         #include "csp_logger.h"
22         #include <string>
23         #include <algorithm>
24         #include <cctype>
25         #include <QDir>
26         #include <QFileInfo>
27 #elif defined(_WIN32)
28         #include <shlwapi.h>
29         #pragma comment(lib, "shlwapi.lib")
30 #else
31         #include <time.h>
32 #endif
33 #include <math.h>
34 #include "common.h"
35 #include "fileio.h"
36
37 #if defined(__MINGW32__) || defined(__MINGW64__)
38         extern DWORD GetLongPathName(LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer);
39 #endif
40 #if defined(_USE_QT)
41         std::string DLL_PREFIX cpp_homedir;
42         std::string DLL_PREFIX my_procname;
43         std::string DLL_PREFIX sRssDir;
44 #endif
45
46 void DLL_PREFIX common_initialize()
47 {
48         // get the initial current path when the software starts
49         get_initial_current_path();
50 }
51
52 uint32_t DLL_PREFIX EndianToLittle_DWORD(uint32_t x)
53 {
54 #if defined(__LITTLE_ENDIAN__)
55         return x;
56 #else
57         uint32_t y;
58         y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
59             ((x & 0x00ff0000) >> 8)  | ((x & 0xff000000) >> 24);
60         return y;
61 #endif
62 }
63
64 uint16_t DLL_PREFIX EndianToLittle_WORD(uint16_t x)
65 {
66 #if defined(__LITTLE_ENDIAN__)
67         return x;
68 #else
69         uint16_t y;
70         y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
71         return y;
72 #endif
73 }
74
75 uint32_t DLL_PREFIX EndianFromLittle_DWORD(uint32_t x)
76 {
77 #if defined(__LITTLE_ENDIAN__)
78         return x;
79 #else
80         uint32_t y;
81         y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
82             ((x & 0x00ff0000) >> 8)  | ((x & 0xff000000) >> 24);
83         return y;
84 #endif
85 }
86
87 uint16_t DLL_PREFIX EndianFromLittle_WORD(uint16_t x)
88 {
89 #if defined(__LITTLE_ENDIAN__)
90         return x;
91 #else
92         uint16_t y;
93         y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
94         return y;
95 #endif
96 }
97
98
99 uint32_t DLL_PREFIX EndianToBig_DWORD(uint32_t x)
100 {
101 #if defined(__BIG_ENDIAN__)
102         return x;
103 #else
104         uint32_t y;
105         y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
106             ((x & 0x00ff0000) >> 8)  | ((x & 0xff000000) >> 24);
107         return y;
108 #endif
109 }
110
111 uint16_t DLL_PREFIX EndianToBig_WORD(uint16_t x)
112 {
113 #if defined(__BIG_ENDIAN__)
114         return x;
115 #else
116         uint16_t y;
117         y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
118         return y;
119 #endif
120 }
121
122 uint32_t DLL_PREFIX EndianFromBig_DWORD(uint32_t x)
123 {
124 #if defined(__BIG_ENDIAN__)
125         return x;
126 #else
127         uint32_t y;
128         y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
129             ((x & 0x00ff0000) >> 8)  | ((x & 0xff000000) >> 24);
130         return y;
131 #endif
132 }
133
134 uint16_t DLL_PREFIX EndianFromBig_WORD(uint16_t x)
135 {
136 #if defined(__BIG_ENDIAN__)
137         return x;
138 #else
139         uint16_t y;
140         y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
141         return y;
142 #endif
143 }
144
145
146 #ifndef _MSC_VER
147 int DLL_PREFIX max(int a, int b)
148 {
149         if(a > b) {
150                 return a;
151         } else {
152                 return b;
153         }
154 }
155
156
157 unsigned DLL_PREFIX int max(unsigned int a, int b)
158 {
159         if(b < 0) return a;
160         if(a > (unsigned int)b) {
161                 return a;
162         } else {
163                 return b;
164         }
165 }
166
167 unsigned DLL_PREFIX int max(int a, unsigned int b)
168 {
169         if(a < 0) return b;
170         if((unsigned int)a > b) {
171                 return a;
172         } else {
173                 return b;
174         }
175 }
176
177 unsigned int DLL_PREFIX max(unsigned int a, unsigned int b)
178 {
179         if(a > b) {
180                 return a;
181         } else {
182                 return b;
183         }
184 }
185
186 int DLL_PREFIX min(int a, int b)
187 {
188         if(a < b) {
189                 return a;
190         } else {
191                 return b;
192         }
193 }
194
195 int DLL_PREFIX min(unsigned int a, int b)
196 {
197         if(b < 0) return b;
198         if(a > INT_MAX) return b;
199         
200         if((int)a < b) {
201                 return (int)a;
202         } else {
203                 return b;
204         }
205 }
206
207 int DLL_PREFIX min(int a, unsigned int b)
208 {
209         if(a < 0) return a;
210         if(b > INT_MAX) return a;
211         
212         if(a < (int)b) {
213                 return a;
214         } else {
215                 return (int)b;
216         }
217 }
218
219 unsigned int DLL_PREFIX min(unsigned int a, unsigned int b)
220 {
221         if(a < b) {
222                 return a;
223         } else {
224                 return b;
225         }
226 }
227 #endif
228
229 #ifndef SUPPORT_SECURE_FUNCTIONS
230 //errno_t my_tfopen_s(FILE** pFile, const _TCHAR *filename, const _TCHAR *mode)
231 //{
232 //      if((*pFile = _tfopen(filename, mode)) != NULL) {
233 //              return 0;
234 //      } else {
235 //              return errno;
236 //      }
237 //}
238
239 errno_t DLL_PREFIX my_tcscat_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
240 {
241         _tcscat(strDestination, strSource);
242         return 0;
243 }
244
245 errno_t DLL_PREFIX my_strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource)
246 {
247         strcpy(strDestination, strSource);
248         return 0;
249 }
250
251 errno_t DLL_PREFIX my_tcscpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
252 {
253         _tcscpy(strDestination, strSource);
254         return 0;
255 }
256
257 errno_t DLL_PREFIX my_strncpy_s(char *strDestination, size_t numberOfElements, const char *strSource, size_t count)
258 {
259         strncpy(strDestination, strSource, count);
260         return 0;
261 }
262
263 errno_t DLL_PREFIX my_tcsncpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource, size_t count)
264 {
265         _tcsncpy(strDestination, strSource, count);
266         return 0;
267 }
268
269 char *DLL_PREFIX my_strtok_s(char *strToken, const char *strDelimit, char **context)
270 {
271         return strtok(strToken, strDelimit);
272 }
273
274 _TCHAR *DLL_PREFIX my_tcstok_s(_TCHAR *strToken, const char *strDelimit, _TCHAR **context)
275 {
276         return _tcstok(strToken, strDelimit);
277 }
278
279 int DLL_PREFIX my_sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
280 {
281         va_list ap;
282         va_start(ap, format);
283         int result = vsnprintf(buffer, sizeOfBuffer, format, ap);
284         va_end(ap);
285         return result;
286 }
287
288 int DLL_PREFIX my_swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, ...)
289 {
290         va_list ap;
291         va_start(ap, format);
292         int result = vswprintf(buffer, sizeOfBuffer, format, ap);
293         va_end(ap);
294         return result;
295 }
296
297 int DLL_PREFIX my_stprintf_s(_TCHAR *buffer, size_t sizeOfBuffer, const _TCHAR *format, ...)
298 {
299         va_list ap;
300         va_start(ap, format);
301         int result = vsnprintf(buffer, sizeOfBuffer, format, ap);
302         va_end(ap);
303         return result;
304 }
305
306 int DLL_PREFIX my_vsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr)
307 {
308         return vsnprintf(buffer, numberOfElements * sizeof(char), format, argptr);
309 }
310
311 int DLL_PREFIX my_vstprintf_s(_TCHAR *buffer, size_t numberOfElements, const _TCHAR *format, va_list argptr)
312 {
313         return vsnprintf(buffer, numberOfElements * sizeof(_TCHAR), format, argptr);
314 }
315 #endif
316
317 //#ifdef USE_FAST_MEMCPY
318
319 void DLL_PREFIX *my_memcpy(void *dst, void *src, size_t len)
320 {
321         return memcpy(dst, src, len);
322 }
323 //#endif
324
325
326 #ifndef _WIN32
327 BOOL DLL_PREFIX MyWritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName)
328 {
329         BOOL result = FALSE;
330         FILEIO* fio_i = new FILEIO();
331         if(fio_i->Fopen(lpFileName, FILEIO_READ_ASCII)) {
332                 char tmp_path[_MAX_PATH];
333                 my_sprintf_s(tmp_path, _MAX_PATH, "%s.$$$", lpFileName);
334                 FILEIO* fio_o = new FILEIO();
335                 if(fio_o->Fopen(tmp_path, FILEIO_WRITE_ASCII)) {
336                         bool in_section = false;
337                         char section[1024], line[1024], *equal;
338                         my_sprintf_s(section, 1024, "[%s]", lpAppName);
339                         while(fio_i->Fgets(line, 1024) != NULL && strlen(line) > 0) {
340                                 if(line[strlen(line) - 1] == '\n') {
341                                         line[strlen(line) - 1] = '\0';
342                                 }
343                                 if(!result) {
344                                         if(line[0] == '[') {
345                                                 if(in_section) {
346                                                         fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
347                                                         result = TRUE;
348                                                 } else if(strcmp(line, section) == 0) {
349                                                         in_section = true;
350                                                 }
351                                         } else if(in_section && (equal = strstr(line, "=")) != NULL) {
352                                                 *equal = '\0';
353                                                 if(strcmp(line, lpKeyName) == 0) {
354                                                         fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
355                                                         result = TRUE;
356                                                         continue;
357                                                 }
358                                                 *equal = '=';
359                                         }
360                                 }
361                                 fio_o->Fprintf("%s\n", line);
362                         }
363                         if(!result) {
364                                 if(!in_section) {
365                                         fio_o->Fprintf("[%s]\n", lpAppName);
366                                 }
367                                 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
368                                 result = TRUE;
369                         }
370                         fio_o->Fclose();
371                 }
372                 delete fio_o;
373                 fio_i->Fclose();
374                 if(result) {
375                         if(!(FILEIO::RemoveFile(lpFileName) && FILEIO::RenameFile(tmp_path, lpFileName))) {
376                                 result = FALSE;
377                         }
378                 }
379         } else {
380                 FILEIO* fio_o = new FILEIO();
381                 if(fio_o->Fopen(lpFileName, FILEIO_WRITE_ASCII)) {
382                         fio_o->Fprintf("[%s]\n", lpAppName);
383                         fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
384                         fio_o->Fclose();
385                 }
386                 delete fio_o;
387         }
388         delete fio_i;
389         return result;
390 }
391
392
393 DWORD DLL_PREFIX MyGetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName)
394 {
395         _TCHAR *lpp = (_TCHAR *)lpReturnedString;
396         if(lpDefault != NULL) {
397                 my_strcpy_s(lpp, nSize, lpDefault);
398         } else {
399                 lpp[0] = '\0';
400         }
401         FILEIO* fio = new FILEIO();
402         if(!(fio->IsFileExisting(lpFileName))) return 0;
403         if(fio->Fopen(lpFileName, FILEIO_READ_ASCII)) {
404                 bool in_section = false;
405                 char section[1024], line[1024], *equal;
406                 my_sprintf_s(section, 1024, "[%s]", lpAppName);
407                 while(fio->Fgets(line, 1024) != NULL && strlen(line) > 0) {
408                         if(line[strlen(line) - 1] == '\n') {
409                                 line[strlen(line) - 1] = '\0';
410                         }
411                         if(line[0] == '[') {
412                                 if(in_section) {
413                                         break;
414                                 } else if(strcmp(line, section) == 0) {
415                                         in_section = true;
416                                 }
417                         } else if(in_section && (equal = strstr(line, "=")) != NULL) {
418                                 *equal = '\0';
419                                 if(strcmp(line, lpKeyName) == 0) {
420                                         my_strcpy_s(lpp, nSize, equal + 1);
421                                         break;
422                                 }
423                         }
424                 }
425                 fio->Fclose();
426         }
427         delete fio;
428         csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Try App: %s Key: %s", lpAppName, lpKeyName);
429         return strlen(lpp);
430 }
431
432 UINT DLL_PREFIX MyGetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName)
433 {
434         int i;
435         char sstr[128];
436         char sval[128];
437         std::string s;
438         memset(sstr, 0x00, sizeof(sstr));
439         memset(sval, 0x00, sizeof(sval));
440         snprintf(sval, 128, "%d", nDefault); 
441         MyGetPrivateProfileString(lpAppName,lpKeyName, sval, sstr, 128, lpFileName);
442         s = sstr;
443         
444         if(s.empty()) {
445                 i = nDefault;
446         } else {
447                 i = strtol(s.c_str(), NULL, 10);
448         }
449         //csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Got Int: %d\n", i);
450         return i;
451 }
452 #endif
453
454 #if defined(_RGB555)
455 scrntype_t DLL_PREFIX RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
456 {
457         scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
458         scrntype_t gg = ((scrntype_t)g * 0x1f) / 0xff;
459         scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
460         return (rr << 10) | (gg << 5) | bb;
461 }
462
463 scrntype_t DLL_PREFIX RGBA_COLOR(uint32_t r, uint32_t g, uint b, uint32_t a)
464 {
465         return RGB_COLOR(r, g, b);
466 }
467
468 uint8_t DLL_PREFIX R_OF_COLOR(scrntype_t c)
469 {
470         c = (c >> 10) & 0x1f;
471         c = (c * 0xff) / 0x1f;
472         return (uint8_t)c;
473 }
474
475 uint8_t DLL_PREFIX G_OF_COLOR(scrntype_t c)
476 {
477         c = (c >>  5) & 0x1f;
478         c = (c * 0xff) / 0x1f;
479         return (uint8_t)c;
480 }
481
482 uint8_t DLL_PREFIX B_OF_COLOR(scrntype_t c)
483 {
484         c = (c >>  0) & 0x1f;
485         c = (c * 0xff) / 0x1f;
486         return (uint8_t)c;
487 }
488
489 uint8_t DLL_PREFIX A_OF_COLOR(scrntype_t c)
490 {
491         return 0xff; //
492 }
493 #elif defined(_RGB565)
494 scrntype_t DLL_PREFIX RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
495 {
496         scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
497         scrntype_t gg = ((scrntype_t)g * 0x3f) / 0xff;
498         scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
499         return (rr << 11) | (gg << 5) | bb;
500 }
501
502 scrntype_t DLL_PREFIX RGBA_COLOR(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
503 {
504         return RGB_COLOR(r, g, b);
505 }
506
507 uint8_t DLL_PREFIX R_OF_COLOR(scrntype_t c)
508 {
509         c = (c >> 11) & 0x1f;
510         c = (c * 0xff) / 0x1f;
511         return (uint8_t)c;
512 }
513
514 uint8_t DLL_PREFIX G_OF_COLOR(scrntype_t c)
515 {
516         c = (c >>  5) & 0x3f;
517         c = (c * 0xff) / 0x3f;
518         return (uint8_t)c;
519 }
520
521 uint8_t DLL_PREFIX B_OF_COLOR(scrntype_t c)
522 {
523         c = (c >>  0) & 0x1f;
524         c = (c * 0xff) / 0x1f;
525         return (uint8_t)c;
526 }
527
528 uint8_t DLL_PREFIX A_OF_COLOR(scrntype_t c)
529 {
530         return 0xff; // Alpha = 255
531 }
532 #endif
533
534 // Note: table strongly recommend to be aligned by sizeof(uint16_vec8_t).
535 // This is sizeof(uint16) * 8, some compilers may require to align 16bytes(128)
536 // when using SIMD128 -- 20181105 K.O
537 void DLL_PREFIX PrepareBitTransTableUint16(_bit_trans_table_t *tbl, uint16_t on_val, uint16_t off_val)
538 {
539         if(tbl == NULL) return;
540 __DECL_VECTORIZED_LOOP
541         for(uint16_t i = 0; i < 256; i++) {
542                 uint16_t n = i;
543 __DECL_VECTORIZED_LOOP
544                 for(int j = 0; j < 8; j++) {
545                         tbl->plane_table[i].w[j] = ((n & 0x80) == 0) ? off_val : on_val;
546                         n <<= 1;
547                 }
548         }
549 }
550
551 // Note: table strongly recommend to be aligned by sizeof(scrntype_vec8_t).
552 // This is sizeof(uint16) * 8, some compilers may require to align 32bytes(256) or 16bytes(128)
553 // when using SIMD256 or SIMD128 -- 20181105 K.O
554 void DLL_PREFIX PrepareBitTransTableScrnType(_bit_trans_table_scrn_t *tbl, scrntype_t on_val, scrntype_t off_val)
555 {
556         if(tbl == NULL) return;
557 __DECL_VECTORIZED_LOOP
558         for(uint16_t i = 0; i < 256; i++) {
559                 uint16_t n = i;
560 __DECL_VECTORIZED_LOOP
561                 for(int j = 0; j < 8; j++) {
562                         tbl->plane_table[i].w[j] = ((n & 0x80) == 0) ? off_val : on_val;
563                         n <<= 1;
564                 }
565         }
566 }
567
568 // Prepare reverse byte-order table(s).
569 void DLL_PREFIX PrepareReverseBitTransTableUint16(_bit_trans_table_t *tbl, uint16_t on_val, uint16_t off_val)
570 {
571         if(tbl == NULL) return;
572 __DECL_VECTORIZED_LOOP
573         for(uint16_t i = 0; i < 256; i++) {
574                 uint16_t n = i;
575 __DECL_VECTORIZED_LOOP
576                 for(int j = 0; j < 8; j++) {
577                         tbl->plane_table[i].w[j] = ((n & 0x01) == 0) ? off_val : on_val;
578                         n >>= 1;
579                 }
580         }
581 }
582
583 void DLL_PREFIX PrepareReverseBitTransTableScrnType(_bit_trans_table_scrn_t *tbl, scrntype_t on_val, scrntype_t off_val)
584 {
585         if(tbl == NULL) return;
586 __DECL_VECTORIZED_LOOP
587         for(uint16_t i = 0; i < 256; i++) {
588                 uint16_t n = i;
589 __DECL_VECTORIZED_LOOP
590                 for(int j = 0; j < 8; j++) {
591                         tbl->plane_table[i].w[j] = ((n & 0x01) == 0) ? off_val : on_val;
592                         n >>= 1;
593                 }
594         }
595 }
596
597 // With _bit_trans_table_scrn_t.
598 void DLL_PREFIX ConvertByteToPackedPixelByColorTable2(uint8_t *src, scrntype_t* dst, int bytes, _bit_trans_table_scrn_t *tbl, scrntype_t *on_color_table, scrntype_t* off_color_table)
599 {
600         
601     scrntype_vec8_t tmpd;
602         scrntype_vec8_t tmpdd;
603         scrntype_vec8_t colors;
604         scrntype_vec8_t* vt = (scrntype_vec8_t*)__builtin_assume_aligned(&(tbl->plane_table[0]), sizeof(scrntype_vec8_t));
605         
606         uintptr_t disalign = (uintptr_t)dst;
607         disalign = disalign & (sizeof(scrntype_vec8_t) - 1); //Is align by 128bits or 256bytes?
608         if(disalign == 0) {
609                 // Yes.
610                 scrntype_vec8_t *vdst = (scrntype_vec8_t*)__builtin_assume_aligned(dst, sizeof(scrntype_vec8_t));
611 __DECL_VECTORIZED_LOOP
612                 for(int i = 0; i < bytes; i++) {
613                         tmpd.v = vt[src[i]].v;
614                         tmpdd.v = ~tmpd.v;
615                         
616 __DECL_VECTORIZED_LOOP
617                         for(int j = 0; j < 8; j++) {
618                                 colors.w[j] = on_color_table[j];
619                         }
620                         tmpd.v = tmpd.v & colors.v;
621 __DECL_VECTORIZED_LOOP
622                         for(int j = 0; j < 8; j++) {
623                                 colors.w[j] = off_color_table[j];
624                         }
625                         tmpdd.v = tmpdd.v & colors.v;
626                         vdst->v = (tmpd.v | tmpdd.v);
627                         off_color_table += 8;
628                         on_color_table += 8;
629                         vdst++;
630                 }
631         } else {
632                 // Sorry, not aligned.
633 __DECL_VECTORIZED_LOOP
634                 for(int i = 0; i < bytes; i++) {
635                         tmpd.v = vt[src[i]].v;
636                         tmpdd.v = ~tmpd.v;
637                         
638 __DECL_VECTORIZED_LOOP
639                         for(int j = 0; j < 8; j++) {
640                                 colors.w[j] = on_color_table[j];
641                         }
642                         tmpd.v = tmpd.v & colors.v;
643 __DECL_VECTORIZED_LOOP
644                         for(int j = 0; j < 8; j++) {
645                                 colors.w[j] = off_color_table[j];
646                         }
647                         tmpdd.v = tmpdd.v & colors.v;
648                         tmpdd.v = tmpdd.v | tmpd.v;
649 __DECL_VECTORIZED_LOOP
650                         for(int j = 0; j < 8; j++) {
651                                 dst[j] = tmpdd.w[j];
652                         }
653                         off_color_table += 8;
654                         on_color_table += 8;
655                         dst += 8;
656                 }
657         }
658 }
659
660
661 // Convert uint8_t[] ed VRAM to uint16_t[] mono pixel pattern.
662 // You must set table to "ON_VALUE" : "OFF_VALUE" via PrepareBitTransTableUint16().
663 // -- 20181105 K.O
664 void DLL_PREFIX ConvertByteToSparceUint16(uint8_t *src, uint16_t* dst, int bytes, _bit_trans_table_t *tbl, uint16_t mask)
665 {
666         
667         uint16_vec8_t   tmpd;
668         uint16_vec8_t*  vt = (uint16_vec8_t*)__builtin_assume_aligned(&(tbl->plane_table[0]), sizeof(uint16_vec8_t));
669
670         uint16_vec8_t __masks;
671
672 __DECL_VECTORIZED_LOOP
673         for(int i = 0; i < 8; i++) {
674                 __masks.w[i] = mask;
675         }
676         uintptr_t disalign = (uintptr_t)dst;
677         disalign = disalign & 0x0f; //Is align by 128bits?
678         if(disalign == 0) {
679                 // Yes.
680                 uint16_vec8_t *vdst = (uint16_vec8_t*)__builtin_assume_aligned(dst, sizeof(uint16_vec8_t));
681 __DECL_VECTORIZED_LOOP
682                 for(int i = 0; i < bytes; i++) {
683                         tmpd.v = vt[src[i]].v;
684                         tmpd.v = tmpd.v & __masks.v;
685                         vdst->v = tmpd.v;
686                         vdst++;
687                 }
688         } else {
689                 // Sorry, not aligned.
690 __DECL_VECTORIZED_LOOP
691                 for(int i = 0; i < bytes; i++) {
692                         tmpd.v = vt[src[i]].v;
693                         tmpd.v = tmpd.v & __masks.v;
694 __DECL_VECTORIZED_LOOP
695                         for(int j = 0; j < 8; j++) {
696                                 dst[j] = tmpd.w[j];
697                         }
698                         dst += 8;
699                 }
700         }
701 }
702
703 // Convert uint8_t[] ed VRAM to uint8_t[] mono pixel pattern.
704 // You must set table to "ON_VALUE" : "OFF_VALUE" via PrepareBitTransTableUint16().
705 // -- 20181105 K.O
706 void DLL_PREFIX ConvertByteToSparceUint8(uint8_t *src, uint16_t* dst, int bytes, _bit_trans_table_t *tbl, uint16_t mask)
707 {
708         
709         uint16_vec8_t   tmpd;
710         uint16_vec8_t*  vt = (uint16_vec8_t*)__builtin_assume_aligned(&(tbl->plane_table[0]), sizeof(uint16_vec8_t));
711
712         uint16_vec8_t __masks;
713         uint8_vec8_t tmpdd;
714
715 __DECL_VECTORIZED_LOOP
716         for(int i = 0; i < 8; i++) {
717                 __masks.w[i] = mask;
718         }
719         uintptr_t disalign = (uintptr_t)dst;
720         disalign = disalign & 0x07; //Is align by 128bits?
721         if(disalign == 0) {
722                 // Yes.
723                 uint8_vec8_t *vdst = (uint8_vec8_t*)__builtin_assume_aligned(dst, sizeof(uint8_vec8_t));
724 __DECL_VECTORIZED_LOOP
725                 for(int i = 0; i < bytes; i++) {
726                         tmpd.v = vt[src[i]].v;
727                         tmpd.v = tmpd.v & __masks.v;
728 __DECL_VECTORIZED_LOOP
729                         for(int j = 0; j < 8; j++) {
730                                 tmpdd.w[j] = (uint8_t)(tmpd.w[j]);
731                         }
732                         vdst->v = tmpdd.v;
733                         vdst++;
734                 }
735         } else {
736                 // Sorry, not aligned.
737 __DECL_VECTORIZED_LOOP
738                 for(int i = 0; i < bytes; i++) {
739                         tmpd.v = vt[src[i]].v;
740                         tmpd.v = tmpd.v & __masks.v;
741 __DECL_VECTORIZED_LOOP
742                         for(int j = 0; j < 8; j++) {
743                                 dst[j] = (uint8_t)(tmpd.w[j]);
744                         }
745                         dst += 8;
746                 }
747         }
748 }
749
750
751 void DLL_PREFIX ConvertByteToPackedPixelByColorTable(uint8_t *src, scrntype_t* dst, int bytes, _bit_trans_table_t *tbl, scrntype_t *on_color_table, scrntype_t* off_color_table)
752 {
753         
754         uint16_vec8_t   tmpd;
755         scrntype_vec8_t tmpdd;
756         uint16_vec8_t*  vt = (uint16_vec8_t*)__builtin_assume_aligned(&(tbl->plane_table[0]), sizeof(uint16_vec8_t));
757         
758         uintptr_t disalign = (uintptr_t)dst;
759         disalign = disalign & 0x0f; //Is align by 128bits?
760         if(disalign == 0) {
761                 // Yes.
762                 scrntype_vec8_t *vdst = (scrntype_vec8_t*)__builtin_assume_aligned(dst, sizeof(scrntype_vec8_t));
763 __DECL_VECTORIZED_LOOP
764                 for(int i = 0; i < bytes; i++) {
765                         tmpd.v = vt[src[i]].v;
766 __DECL_VECTORIZED_LOOP
767                         for(int j = 0; j < 8; j++) {
768                                 tmpdd.w[j] = (tmpd.w[j] == 0) ? off_color_table[j] : on_color_table[j];
769                         }
770                         vdst->v = tmpdd.v;
771                         off_color_table += 8;
772                         on_color_table += 8;
773                         vdst++;
774                 }
775         } else {
776                 // Sorry, not aligned.
777 __DECL_VECTORIZED_LOOP
778                 for(int i = 0; i < bytes; i++) {
779                         tmpd.v = vt[src[i]].v;
780 __DECL_VECTORIZED_LOOP
781                         for(int j = 0; j < 8; j++) {
782                                 dst[j] = (tmpd.w[j] == 0) ? off_color_table[j] : on_color_table[j];
783                         }
784                         off_color_table += 8;
785                         on_color_table += 8;
786                         dst += 8;
787                 }
788         }
789 }
790
791
792 void DLL_PREFIX Render8Colors_Line(_render_command_data_t *src, scrntype_t *dst, scrntype_t* dst2, bool scan_line)
793 {
794         if(src == NULL) return;
795         if(dst == NULL) return;
796
797 //__DECL_VECTORIZED_LOOP
798 //      for(int i = 0; i < 3; i++) {
799 //              if(src->bit_trans_table[i] == NULL) return;
800 //              if(src->data[i] == NULL) return;
801 //      }
802         scrntype_t dummy_palette[8]; // fallback
803         scrntype_t *palette = src->palette;
804         
805         uint16_vec8_t *vpb = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[0], sizeof(uint16_vec8_t));
806         uint16_vec8_t *vpr = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[1], sizeof(uint16_vec8_t));
807         uint16_vec8_t *vpg = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[2], sizeof(uint16_vec8_t));
808
809         uint32_t x;
810         __DECL_ALIGNED(16) uint32_t offset[4] = {0};
811         __DECL_ALIGNED(16) uint32_t beginaddr[4] = {0};
812         uint32_t mask = src->addrmask;
813         uint32_t offsetmask = src->addrmask2;
814 __DECL_VECTORIZED_LOOP
815         for(int i = 0; i < 3; i++) {
816                 offset[i] = src->voffset[i];
817         }
818         if(palette == NULL) {
819 __DECL_VECTORIZED_LOOP
820                 for(int i = 0; i < 8; i++) {
821                         dummy_palette[i] = RGB_COLOR(((i & 2) << 5) | 0x1f,
822                                                                                  ((i & 4) << 5) | 0x1f,
823                                                                                  ((i & 1) << 5) | 0x1f);
824                 }
825                 palette = dummy_palette;
826         }
827         uint8_t *bp = &(src->data[0][src->baseaddress[0]]);
828         uint8_t *rp = &(src->data[1][src->baseaddress[1]]);
829         uint8_t *gp = &(src->data[2][src->baseaddress[2]]);
830         
831         uint8_t r, g, b;
832         int shift = src->shift;
833         const bool is_render[3] = { src->is_render[0], src->is_render[1],  src->is_render[2] };
834         uint16_vec8_t tmpd;
835         scrntype_vec8_t tmp_dd; 
836         scrntype_vec8_t* vdp = (scrntype_vec8_t*)__builtin_assume_aligned(dst, sizeof(scrntype_vec8_t));
837         
838         x = src->begin_pos;
839         uint32_t n = x;
840         if(dst2 == NULL) {
841         __DECL_VECTORIZED_LOOP
842                 for(uint32_t xx = 0; xx < src->render_width; xx++) {
843                         b = (is_render[0]) ? bp[(offset[0] + n) & mask] : 0;
844                         r = (is_render[1]) ? rp[(offset[1] + n) & mask] : 0;
845                         g = (is_render[2]) ? gp[(offset[2] + n) & mask] : 0;
846                         tmpd.v = vpb[b].v;
847                         tmpd.v = tmpd.v | vpr[r].v;
848                         tmpd.v = tmpd.v | vpg[g].v;
849                         tmpd.v = tmpd.v >> shift;
850                         n = (n + 1) & offsetmask;
851         __DECL_VECTORIZED_LOOP
852                         for(int i = 0; i < 8; i++) {
853                                 tmp_dd.w[i] = palette[tmpd.w[i]];
854                         }
855                         vdp[xx].v = tmp_dd.v;
856                 }
857         } else {
858 #if defined(_RGB555) || defined(_RGBA565)
859                 static const int shift_factor = 2;
860 #else // 24bit
861                 static const int shift_factor = 3;
862 #endif
863                 scrntype_vec8_t sline;
864                 scrntype_vec8_t* vdp2 = (scrntype_vec8_t*)__builtin_assume_aligned(dst2, sizeof(scrntype_vec8_t));
865         __DECL_VECTORIZED_LOOP
866                 for(int i = 0; i < 8; i++) {
867                         sline.w[i] = (scrntype_t)RGBA_COLOR(31, 31, 31, 255);
868                 }
869         __DECL_VECTORIZED_LOOP
870                 for(uint32_t xx = 0; xx < src->render_width; xx++) {
871                         b = (is_render[0]) ? bp[(offset[0] + n) & mask] : 0;
872                         r = (is_render[1]) ? rp[(offset[1] + n) & mask] : 0;
873                         g = (is_render[2]) ? gp[(offset[2] + n) & mask] : 0;
874                         tmpd.v = vpb[b].v;
875                         tmpd.v = tmpd.v | vpr[r].v;
876                         tmpd.v = tmpd.v | vpg[g].v;
877                         tmpd.v = tmpd.v >> shift;
878                         n = (n + 1) & offsetmask;
879         __DECL_VECTORIZED_LOOP
880                         for(int i = 0; i < 8; i++) {
881                                 tmp_dd.w[i] = palette[tmpd.w[i]];
882                         }
883                         vdp[xx].v = tmp_dd.v;
884                         if(scan_line) {
885                                 tmp_dd.v = tmp_dd.v >> shift_factor;
886                                 tmp_dd.v = tmp_dd.v & sline.v;
887                         }
888                         vdp2[xx].v = tmp_dd.v;
889                 }
890         }
891 }
892
893 void DLL_PREFIX Render16Colors_Line(_render_command_data_t *src, scrntype_t *dst, scrntype_t* dst2, bool scan_line)
894 {
895         if(src == NULL) return;
896         if(dst == NULL) return;
897
898 //__DECL_VECTORIZED_LOOP
899 //      for(int i = 0; i < 3; i++) {
900 //              if(src->bit_trans_table[i] == NULL) return;
901 //              if(src->data[i] == NULL) return;
902 //      }
903         scrntype_t dummy_palette[16]; // fallback
904         scrntype_t *palette = src->palette;
905         
906         uint16_vec8_t *vpb = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[0], sizeof(uint16_vec8_t));
907         uint16_vec8_t *vpr = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[1], sizeof(uint16_vec8_t));
908         uint16_vec8_t *vpg = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[2], sizeof(uint16_vec8_t));
909         uint16_vec8_t *vpn = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[3], sizeof(uint16_vec8_t));
910
911         uint32_t x;
912         __DECL_ALIGNED(16) uint32_t offset[4];
913         __DECL_ALIGNED(16) uint32_t beginaddr[4];
914         uint32_t mask = src->addrmask;
915         uint32_t offsetmask = src->addrmask2;
916         
917 __DECL_VECTORIZED_LOOP
918         for(int i = 0; i < 4; i++) {
919                 offset[i] = src->voffset[i];
920         }
921         if(palette == NULL) {
922 __DECL_VECTORIZED_LOOP
923                 for(int i = 0; i < 16; i++) {
924                         dummy_palette[i] = RGB_COLOR((((i & 2) + (i & 8)) << 4) | 0x0f,
925                                                                                  (((i & 4) + (i & 8)) << 4) | 0x0f,
926                                                                                  (((i & 1) + (i & 8)) << 4) | 0x0f);
927                 }
928                 palette = dummy_palette;
929         }
930         uint8_t *bp = &(src->data[0][src->baseaddress[0]]);
931         uint8_t *rp = &(src->data[1][src->baseaddress[1]]);
932         uint8_t *gp = &(src->data[2][src->baseaddress[2]]);
933         uint8_t *np = &(src->data[3][src->baseaddress[3]]);
934         
935         uint8_t r, g, b, n;
936         int shift = src->shift;
937         const bool is_render[4] = { src->is_render[0], src->is_render[1],  src->is_render[2], src->is_render[3] };
938         uint16_vec8_t tmpd;
939         scrntype_vec8_t tmp_dd; 
940         scrntype_vec8_t* vdp = (scrntype_vec8_t*)__builtin_assume_aligned(dst, sizeof(scrntype_vec8_t));
941         
942         x = src->begin_pos;
943         uint32_t xn = x;
944         if(dst2 == NULL) {      
945         __DECL_VECTORIZED_LOOP
946                 for(uint32_t xx = 0; xx < src->render_width; xx++) {
947                         b = (is_render[0]) ? bp[(offset[0] + xn) & mask] : 0;
948                         r = (is_render[1]) ? rp[(offset[1] + xn) & mask] : 0;
949                         g = (is_render[2]) ? gp[(offset[2] + xn) & mask] : 0;
950                         n = (is_render[3]) ? np[(offset[3] + xn) & mask] : 0;
951                         tmpd.v = vpb[b].v;
952                         tmpd.v = tmpd.v | vpr[r].v;
953                         tmpd.v = tmpd.v | vpg[g].v;
954                         tmpd.v = tmpd.v | vpn[n].v;
955                         tmpd.v = tmpd.v >> shift;
956                         xn = (xn + 1) & offsetmask;
957         __DECL_VECTORIZED_LOOP
958                         for(int i = 0; i < 8; i++) {
959                                 tmp_dd.w[i] = palette[tmpd.w[i]];
960                         }
961                         vdp[xx].v = tmp_dd.v;
962                 }
963         } else {
964 #if defined(_RGB555) || defined(_RGBA565)
965                 static const int shift_factor = 2;
966 #else // 24bit
967                 static const int shift_factor = 3;
968 #endif
969                 scrntype_vec8_t sline;
970                 scrntype_vec8_t* vdp2 = (scrntype_vec8_t*)__builtin_assume_aligned(dst2, sizeof(scrntype_vec8_t));
971         __DECL_VECTORIZED_LOOP
972                 for(int i = 0; i < 8; i++) {
973                         sline.w[i] = (scrntype_t)RGBA_COLOR(31, 31, 31, 255);
974                 }
975         __DECL_VECTORIZED_LOOP
976                 for(uint32_t xx = 0; xx < src->render_width; xx++) {
977                         b = (is_render[0]) ? bp[(offset[0] + xn) & mask] : 0;
978                         r = (is_render[1]) ? rp[(offset[1] + xn) & mask] : 0;
979                         g = (is_render[2]) ? gp[(offset[2] + xn) & mask] : 0;
980                         n = (is_render[3]) ? np[(offset[3] + xn) & mask] : 0;
981                         tmpd.v = vpb[b].v;
982                         tmpd.v = tmpd.v | vpr[r].v;
983                         tmpd.v = tmpd.v | vpg[g].v;
984                         tmpd.v = tmpd.v | vpn[n].v;
985                         tmpd.v = tmpd.v >> shift;
986                         xn = (xn + 1) & offsetmask;
987         __DECL_VECTORIZED_LOOP
988                         for(int i = 0; i < 8; i++) {
989                                 tmp_dd.w[i] = palette[tmpd.w[i]];
990                         }
991                         vdp[xx].v = tmp_dd.v;
992                         if(scan_line) {
993                                 tmp_dd.v = tmp_dd.v >> shift_factor;
994                                 tmp_dd.v = tmp_dd.v & sline.v;
995                         }
996                         vdp2[xx].v = tmp_dd.v;
997                 }
998         }
999 }
1000
1001 // src->palette Must be 2^planes entries.
1002 void DLL_PREFIX Render2NColors_Line(_render_command_data_t *src, scrntype_t *dst, scrntype_t* dst2, bool scan_line, int planes)
1003 {
1004         if(src == NULL) return;
1005         if(dst == NULL) return;
1006         if(src->palette == NULL) return;
1007         if(planes <= 0) return;
1008         if(planes >= 16) planes = 16;
1009 //__DECL_VECTORIZED_LOOP
1010 //      for(int i = 0; i < 3; i++) {
1011 //              if(src->bit_trans_table[i] == NULL) return;
1012 //              if(src->data[i] == NULL) return;
1013 //      }
1014         scrntype_t *palette = src->palette;
1015         
1016         uint16_vec8_t* vp[16];
1017         for(int i = 0; i < planes; i++) {
1018                 vp[i] = (uint16_vec8_t*)__builtin_assume_aligned(src->bit_trans_table[i], sizeof(uint16_vec8_t));
1019         }
1020
1021         uint32_t x;
1022         __DECL_ALIGNED(16) uint32_t offset[16];
1023         __DECL_ALIGNED(16) uint32_t beginaddr[16];
1024         uint32_t mask = src->addrmask;
1025         uint32_t offsetmask = src->addrmask2;
1026 __DECL_VECTORIZED_LOOP
1027         for(int i = 0; i < planes; i++) {
1028                 offset[i] = src->voffset[i];
1029         }
1030         uint8_t *pp[16];
1031         for(int i = 0; i < planes; i++) {
1032                 pp[i] = &(src->data[i][src->baseaddress[i]]);
1033         }
1034         
1035         uint8_t d[16];
1036         int shift = src->shift;
1037         const bool is_render[4] = { src->is_render[0], src->is_render[1],  src->is_render[2], src->is_render[3] };
1038         uint16_vec8_t tmpd;
1039         scrntype_vec8_t tmp_dd; 
1040         scrntype_vec8_t* vdp = (scrntype_vec8_t*)__builtin_assume_aligned(dst, sizeof(scrntype_vec8_t));
1041         
1042         x = src->begin_pos;
1043         if(dst2 == NULL) {
1044                 uint32_t n = x;
1045         __DECL_VECTORIZED_LOOP
1046                 for(uint32_t xx = 0; xx < src->render_width; xx++) {
1047                         d[0] = (is_render[0]) ? pp[0][(offset[0] + n) & mask] : 0;
1048                         tmpd.v = vp[0][d[0]].v;
1049         __DECL_VECTORIZED_LOOP
1050                         for(int i = 1; i < planes; i++) {
1051                                 d[i] = (is_render[i]) ? pp[i][(offset[i] + n) & mask] : 0;
1052                                 tmpd.v = tmpd.v | vp[i][d[i]].v;
1053                         }
1054                         n = (n + 1) & offsetmask;
1055                         tmpd.v = tmpd.v >> shift;
1056         __DECL_VECTORIZED_LOOP
1057                         for(int i = 0; i < 8; i++) {
1058                                 tmp_dd.w[i] = palette[tmpd.w[i]];
1059                         }
1060                         vdp[xx].v = tmp_dd.v;
1061                 }
1062         } else {
1063 #if defined(_RGB555) || defined(_RGBA565)
1064                 static const int shift_factor = 2;
1065 #else // 24bit
1066                 static const int shift_factor = 3;
1067 #endif
1068                 scrntype_vec8_t sline;
1069                 scrntype_vec8_t* vdp2 = (scrntype_vec8_t*)__builtin_assume_aligned(dst2, sizeof(scrntype_vec8_t));
1070         __DECL_VECTORIZED_LOOP
1071                 for(int i = 0; i < 8; i++) {
1072                         sline.w[i] = (scrntype_t)RGBA_COLOR(31, 31, 31, 255);
1073                 }
1074                 uint32_t n = x;
1075         __DECL_VECTORIZED_LOOP
1076                 for(uint32_t xx = 0; xx < src->render_width; xx++) {
1077                         d[0] = (is_render[0]) ? pp[0][(offset[0] + n) & mask] : 0;
1078                         tmpd.v = vp[0][d[0]].v;
1079         __DECL_VECTORIZED_LOOP
1080                         for(int i = 1; i < planes; i++) {
1081                                 d[i] = (is_render[i]) ? pp[i][(offset[i] + n) & mask] : 0;
1082                                 tmpd.v = tmpd.v | vp[i][d[i]].v;
1083                         }
1084                         n = (n + 1) & offsetmask;
1085                         tmpd.v = tmpd.v >> shift;
1086         __DECL_VECTORIZED_LOOP
1087                         for(int i = 0; i < 8; i++) {
1088                                 tmp_dd.w[i] = palette[tmpd.w[i]];
1089                         }
1090                         vdp[xx].v = tmp_dd.v;
1091                         if(scan_line) {
1092                                 tmp_dd.v = tmp_dd.v >> shift_factor;
1093                                 tmp_dd.v = tmp_dd.v & sline.v;
1094                         }
1095                         vdp2[xx].v = tmp_dd.v;
1096                 }
1097         }
1098 }
1099
1100 void DLL_PREFIX Convert2NColorsToByte_Line(_render_command_data_t *src, uint8_t *dst, int planes)
1101 {
1102         if(planes >= 8) planes = 8;
1103         if(planes <= 0) return;
1104
1105         uint8_t* srcp[8];
1106         __DECL_ALIGNED(32) uint32_t offset[8] = {0};
1107         uint16_vec8_t dat;
1108         uint16_vec8_t* bp[8] ;
1109                 
1110 __DECL_VECTORIZED_LOOP
1111                 for(int i = 0; i < planes; i++) {
1112                 bp[i] = (uint16_vec8_t*)__builtin_assume_aligned(&(src->bit_trans_table[i]->plane_table[0]), sizeof(uint16_vec8_t));
1113                 srcp[i] = &(src->data[i][src->baseaddress[i]]);
1114         }
1115         uint32_t addrmask = src->addrmask;
1116         uint32_t offsetmask = src->addrmask2;
1117         int shift = src->shift;
1118         
1119 __DECL_VECTORIZED_LOOP
1120         for(int i = 0; i < planes; i++) {
1121                 offset[i] = src->voffset[i];
1122         }
1123
1124         uint32_t noffset = src->begin_pos & offsetmask;
1125         uint8_t td[16];
1126 __DECL_VECTORIZED_LOOP
1127         for(int x = 0; x < src->render_width; x++) {
1128 __DECL_VECTORIZED_LOOP
1129                 for(int i = 0; i < planes; i++) {
1130                         td[i] = srcp[i][(noffset + offset[i]) & addrmask];
1131                 }
1132                 noffset = (noffset + 1) & offsetmask;
1133                 dat.v = bp[0][td[0]].v;
1134 __DECL_VECTORIZED_LOOP
1135                 for(int i = 1; i < planes; i++) {
1136                         dat.v = dat.v | bp[i][td[i]].v;
1137                 }
1138                 dat.v = dat.v >> shift;
1139 __DECL_VECTORIZED_LOOP
1140                 for(int i = 0; i < 8; i++) {
1141                         dst[i] = (uint8_t)(dat.w[i]);
1142                 }
1143                 dst += 8;
1144                 
1145         }
1146 }
1147
1148 void DLL_PREFIX Convert2NColorsToByte_LineZoom2(_render_command_data_t *src, uint8_t *dst, int planes)
1149 {
1150         if(planes >= 8) planes = 8;
1151         if(planes <= 0) return;
1152
1153         uint8_t* srcp[8];
1154         __DECL_ALIGNED(32) uint32_t offset[8] = {0};
1155         uint16_vec8_t dat;
1156         uint16_vec8_t* bp[8] ;
1157                 
1158 __DECL_VECTORIZED_LOOP
1159                 for(int i = 0; i < planes; i++) {
1160                 bp[i] = (uint16_vec8_t*)__builtin_assume_aligned(&(src->bit_trans_table[i]->plane_table[0]), sizeof(uint16_vec8_t));
1161                 srcp[i] = &(src->data[i][src->baseaddress[i]]);
1162         }
1163         uint32_t addrmask = src->addrmask;
1164         uint32_t offsetmask = src->addrmask2;
1165         int shift = src->shift;
1166         
1167 __DECL_VECTORIZED_LOOP
1168         for(int i = 0; i < planes; i++) {
1169                 offset[i] = src->voffset[i];
1170         }
1171
1172         uint32_t noffset = src->begin_pos & offsetmask;
1173         uint8_t td[16];
1174 __DECL_VECTORIZED_LOOP
1175         for(int x = 0; x < src->render_width; x++) {
1176 __DECL_VECTORIZED_LOOP
1177                 for(int i = 0; i < planes; i++) {
1178                         td[i] = srcp[i][(noffset + offset[i]) & addrmask];
1179                 }
1180                 noffset = (noffset + 1) & offsetmask;
1181                 dat.v = bp[0][td[0]].v;
1182 __DECL_VECTORIZED_LOOP
1183                 for(int i = 1; i < planes; i++) {
1184                         dat.v = dat.v | bp[i][td[i]].v;
1185                 }
1186                 dat.v = dat.v >> shift;
1187 __DECL_VECTORIZED_LOOP
1188         for(int i = 0, j = 0; i < 16; i +=2, j++) {
1189                         dst[i]     = (uint8_t)(dat.w[j]);
1190                         dst[i + 1] = (uint8_t)(dat.w[j]);
1191                 }
1192                 dst += 16;
1193         }
1194 }
1195
1196 void DLL_PREFIX Convert8ColorsToByte_Line(_render_command_data_t *src, uint8_t *dst)
1197 {
1198         uint8_t *bp = &(src->data[0][src->baseaddress[0]]);
1199         uint8_t *rp = &(src->data[1][src->baseaddress[1]]);
1200         uint8_t *gp = &(src->data[2][src->baseaddress[2]]);
1201         __DECL_ALIGNED(16) uint32_t offset[4] = {0};
1202
1203         uint16_vec8_t rdat;
1204         uint16_vec8_t gdat;
1205         uint16_vec8_t bdat;
1206         uint16_vec8_t tmpd;
1207
1208         uint16_vec8_t* bpb = (uint16_vec8_t*)__builtin_assume_aligned(&(src->bit_trans_table[0]->plane_table[0]), sizeof(uint16_vec8_t));
1209         uint16_vec8_t* bpr = (uint16_vec8_t*)__builtin_assume_aligned(&(src->bit_trans_table[1]->plane_table[0]), sizeof(uint16_vec8_t));
1210         uint16_vec8_t* bpg = (uint16_vec8_t*)__builtin_assume_aligned(&(src->bit_trans_table[2]->plane_table[0]), sizeof(uint16_vec8_t));
1211         
1212         uint32_t addrmask = src->addrmask;
1213         uint32_t offsetmask = src->addrmask2;
1214         int shift = src->shift;
1215         
1216 __DECL_VECTORIZED_LOOP
1217         for(int i = 0; i < 3; i++) {
1218                 offset[i] = src->voffset[i];
1219         }
1220
1221         uint32_t noffset = src->begin_pos & offsetmask;
1222         uint8_t b, r, g;
1223 __DECL_VECTORIZED_LOOP
1224         for(int x = 0; x < src->render_width; x++) {
1225                 b = bp[(noffset + offset[0]) & addrmask];
1226                 r = rp[(noffset + offset[1]) & addrmask];
1227                 g = gp[(noffset + offset[2]) & addrmask];
1228
1229                 noffset = (noffset + 1) & offsetmask;
1230                 
1231                 bdat.v = bpb[b].v;
1232                 rdat.v = bpr[r].v;
1233                 gdat.v = bpg[g].v;
1234                 tmpd.v = bdat.v;
1235                 tmpd.v = tmpd.v | rdat.v;
1236                 tmpd.v = tmpd.v | gdat.v;
1237                 tmpd.v = tmpd.v >> shift;
1238
1239 __DECL_VECTORIZED_LOOP
1240                 for(int i = 0; i < 8; i++) {
1241                         dst[i] = (uint8_t)(tmpd.w[i]);
1242                 }
1243                 dst += 8;
1244         }
1245 }
1246         
1247
1248 #ifndef _MSC_VER
1249 struct to_upper {  // Refer from documentation of libstdc++, GCC5.
1250         char operator() (char c) const { return std::toupper(c); }
1251 };
1252 #endif
1253
1254 #if defined(_USE_QT)
1255 static void _my_mkdir(std::string t_dir)
1256 {
1257         struct stat st;
1258 //#if !defined(__WIN32) && !defined(__WIN64)
1259 //      if(fstatat(AT_FDCWD, csppath.c_str(), &st, 0) != 0) {
1260 //              mkdirat(AT_FDCWD, t_dir.c_str(), 0700); // Not found
1261 //      }
1262 #if defined(_USE_QT)
1263         if(stat(t_dir.c_str(), &st) != 0) {
1264                 QDir dir = QDir::current();
1265                 dir.mkdir(QString::fromStdString(t_dir));
1266                 //dir.mkpath(QString::fromUtf8(app_path));
1267         }
1268 #else
1269         if(stat(csppath.c_str(), &st) != 0) {
1270                 _mkdir(t_dir.c_str()); // Not found
1271         }
1272 #endif
1273 }
1274 #endif
1275
1276 const _TCHAR *DLL_PREFIX get_application_path()
1277 {
1278         static _TCHAR app_path[_MAX_PATH];
1279         static bool initialized = false;
1280         
1281         if(!initialized) {
1282 #if defined(_WIN32) && !defined(_USE_QT)
1283                 _TCHAR tmp_path[_MAX_PATH], *ptr = NULL;
1284                 if(GetModuleFileName(NULL, tmp_path, _MAX_PATH) != 0 && GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr) != 0 && ptr != NULL) {
1285                         *ptr = _T('\0');
1286                 } else {
1287                         my_tcscpy_s(app_path, _MAX_PATH, _T(".\\"));
1288                 }
1289 #else
1290 #if defined(Q_OS_WIN)
1291                 std::string delim = "\\";
1292 #else
1293                 std::string delim = "/";
1294 #endif
1295                 std::string csppath = cpp_homedir + "CommonSourceCodeProject" + delim ;
1296                 _my_mkdir(csppath);
1297            
1298                 std::string cpath = csppath + my_procname + delim;
1299                 _my_mkdir(cpath);
1300                 strncpy(app_path, cpath.c_str(), _MAX_PATH - 1);
1301 #endif
1302                 initialized = true;
1303         }
1304         return (const _TCHAR *)app_path;
1305 }
1306
1307 const _TCHAR *DLL_PREFIX get_initial_current_path()
1308 {
1309         static _TCHAR current_path[_MAX_PATH];
1310         static bool initialized = false;
1311         
1312         if(!initialized) {
1313 #if defined(_WIN32) && !defined(_USE_QT)
1314                 GetCurrentDirectoryA(_MAX_PATH, current_path);
1315 #else
1316                 getcwd(current_path, _MAX_PATH);
1317 #endif
1318                 int len = strlen(current_path);
1319                 if(current_path[len - 1] != '\\' && current_path[len - 1] != '/') {
1320 #if defined(_WIN32) || defined(Q_OS_WIN)
1321                         current_path[len] = '\\';
1322 #else
1323                         current_path[len] = '/';
1324 #endif
1325                         current_path[len + 1] = '\0';
1326                 }
1327
1328                 initialized = true;
1329         }
1330         return (const _TCHAR *)current_path;
1331 }
1332
1333 const _TCHAR *DLL_PREFIX create_local_path(const _TCHAR *format, ...)
1334 {
1335         static _TCHAR file_path[8][_MAX_PATH];
1336         static unsigned int table_index = 0;
1337         unsigned int output_index = (table_index++) & 7;
1338         _TCHAR file_name[_MAX_PATH];
1339         //printf("%d %d\n", table_index, output_index);
1340         va_list ap;
1341         
1342         va_start(ap, format);
1343         my_vstprintf_s(file_name, _MAX_PATH, format, ap);
1344         va_end(ap);
1345         my_stprintf_s(file_path[output_index], _MAX_PATH, _T("%s%s"), get_application_path(), file_name);
1346         return (const _TCHAR *)file_path[output_index];
1347 }
1348
1349 void DLL_PREFIX create_local_path(_TCHAR *file_path, int length, const _TCHAR *format, ...)
1350 {
1351         _TCHAR file_name[_MAX_PATH];
1352         va_list ap;
1353         
1354         va_start(ap, format);
1355         my_vstprintf_s(file_name, _MAX_PATH, format, ap);
1356         va_end(ap);
1357         my_stprintf_s(file_path, length, _T("%s%s"), get_application_path(), file_name);
1358 }
1359
1360 bool DLL_PREFIX is_absolute_path(const _TCHAR *file_path)
1361 {
1362 #ifdef _WIN32
1363         if(_tcslen(file_path) > 2 && ((file_path[0] >= _T('A') && file_path[0] <= _T('Z')) || (file_path[0] >= _T('a') && file_path[0] <= _T('z'))) && file_path[1] == _T(':')) {
1364                 return true;
1365         }
1366 #endif
1367         return (_tcslen(file_path) > 1 && (file_path[0] == _T('/') || file_path[0] == _T('\\')));
1368 }
1369
1370 const _TCHAR *DLL_PREFIX create_date_file_path(const _TCHAR *extension)
1371 {
1372         cur_time_t cur_time;
1373         
1374         get_host_time(&cur_time);
1375         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);
1376 }
1377
1378 void DLL_PREFIX create_date_file_path(_TCHAR *file_path, int length, const _TCHAR *extension)
1379 {
1380         my_tcscpy_s(file_path, length, create_date_file_path(extension));
1381 }
1382
1383 const _TCHAR *DLL_PREFIX create_date_file_name(const _TCHAR *extension)
1384 {
1385         static _TCHAR file_name[8][_MAX_PATH];
1386         static unsigned int table_index = 0;
1387         unsigned int output_index = (table_index++) & 7;
1388         cur_time_t cur_time;
1389         
1390         get_host_time(&cur_time);
1391         my_stprintf_s(file_name[output_index], _MAX_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);
1392         return (const _TCHAR *)file_name[output_index];
1393 }
1394
1395 void DLL_PREFIX create_date_file_name(_TCHAR *file_path, int length, const _TCHAR *extension)
1396 {
1397         my_tcscpy_s(file_path, length, create_date_file_name(extension));
1398 }
1399
1400 bool DLL_PREFIX check_file_extension(const _TCHAR *file_path, const _TCHAR *ext)
1401 {
1402 #if defined(_USE_QT)
1403         std::string s_fpath = file_path;
1404         std::string s_ext = ext;
1405         //bool f = false;
1406         int pos;
1407         std::transform(s_fpath.begin(), s_fpath.end(), s_fpath.begin(), to_upper());
1408         std::transform(s_ext.begin(), s_ext.end(), s_ext.begin(), to_upper());
1409         if(s_fpath.length() < s_ext.length()) return false;
1410         pos = s_fpath.rfind(s_ext.c_str(), s_fpath.length());
1411         if((pos != (int)std::string::npos) && (pos >= ((int)s_fpath.length() - (int)s_ext.length()))) return true; 
1412         return false;
1413 #else
1414         int nam_len = _tcslen(file_path);
1415         int ext_len = _tcslen(ext);
1416         
1417         return (nam_len >= ext_len && _tcsncicmp(&file_path[nam_len - ext_len], ext, ext_len) == 0);
1418 #endif
1419 }
1420
1421 const _TCHAR *DLL_PREFIX get_file_path_without_extensiton(const _TCHAR *file_path)
1422 {
1423         static _TCHAR path[8][_MAX_PATH];
1424         static unsigned int table_index = 0;
1425         unsigned int output_index = (table_index++) & 7;
1426         
1427         my_tcscpy_s(path[output_index], _MAX_PATH, file_path);
1428 #if defined(_WIN32) && defined(_MSC_VER)
1429         PathRemoveExtension(path[output_index]);
1430 #elif defined(_USE_QT)
1431         QString delim;
1432         delim = QString::fromUtf8(".");
1433         QString tmp_path = QString::fromUtf8(file_path);
1434         int n = tmp_path.lastIndexOf(delim);
1435         if(n > 0) {
1436                 tmp_path = tmp_path.left(n);
1437         }
1438         //printf("%s\n", tmp_path.toUtf8().constData());
1439         memset(path[output_index], 0x00, sizeof(_TCHAR) * _MAX_PATH);
1440         strncpy(path[output_index], tmp_path.toUtf8().constData(), _MAX_PATH - 1);
1441 #else
1442 #endif
1443         return (const _TCHAR *)path[output_index];
1444 }
1445
1446 void DLL_PREFIX get_long_full_path_name(const _TCHAR* src, _TCHAR* dst, size_t dst_len)
1447 {
1448 #ifdef _WIN32
1449         _TCHAR tmp[_MAX_PATH];
1450         if(GetFullPathName(src, _MAX_PATH, tmp, NULL) == 0) {
1451                 my_tcscpy_s(dst, dst_len, src);
1452         } else if(GetLongPathName(tmp, dst, _MAX_PATH) == 0) {
1453                 my_tcscpy_s(dst, dst_len, tmp);
1454         }
1455 #elif defined(_USE_QT)
1456         QString tmp_path = QString::fromUtf8(src);
1457         QFileInfo info(tmp_path);
1458         my_tcscpy_s(dst, dst_len, info.absoluteFilePath().toLocal8Bit().constData());
1459 #else
1460         // write code for your environment
1461         
1462 #endif
1463 }
1464
1465 const _TCHAR *DLL_PREFIX get_parent_dir(const _TCHAR* file)
1466 {
1467         static _TCHAR path[8][_MAX_PATH];
1468         static unsigned int table_index = 0;
1469         unsigned int output_index = (table_index++) & 7;
1470         
1471 #ifdef _WIN32
1472         _TCHAR *ptr;
1473         GetFullPathName(file, _MAX_PATH, path[output_index], &ptr);
1474         if(ptr != NULL) {
1475                 *ptr = _T('\0');
1476         }
1477 #elif defined(_USE_QT)
1478         QString delim;
1479 #if defined(Q_OS_WIN)
1480         delim = QString::fromUtf8("\\");
1481 #else
1482         delim = QString::fromUtf8("/");
1483 #endif
1484         QString tmp_path = QString::fromUtf8(file);
1485         int n = tmp_path.lastIndexOf(delim);
1486         if(n > 0) {
1487                 tmp_path = tmp_path.left(n);
1488                 tmp_path.append(delim);
1489         }
1490         //printf("%s\n", tmp_path.toUtf8().constData());
1491         memset(path[output_index], 0x00, sizeof(_TCHAR) * _MAX_PATH);
1492         strncpy(path[output_index], tmp_path.toUtf8().constData(), _MAX_PATH - 1);
1493 #else
1494         // write code for your environment
1495 #endif
1496         return path[output_index];
1497 }
1498
1499 const wchar_t *DLL_PREFIX char_to_wchar(const char *cs)
1500 {
1501         // char to wchar_t
1502         static wchar_t ws[4096];
1503         
1504 #if defined(_WIN32) || defined(_USE_QT)
1505         mbstowcs(ws, cs, strlen(cs));
1506 #else
1507         // write code for your environment
1508 #endif
1509         return ws;
1510 }
1511
1512 const char *DLL_PREFIX wchar_to_char(const wchar_t *ws)
1513 {
1514         // wchar_t to char
1515         static char cs[4096];
1516         
1517 #ifdef _WIN32
1518         wcstombs(cs, ws, wcslen(ws));
1519 #elif defined(_USE_QT)
1520         wcstombs(cs, ws, wcslen(ws));
1521 #else
1522         // write code for your environment
1523 #endif
1524         return cs;
1525 }
1526
1527 const _TCHAR *DLL_PREFIX char_to_tchar(const char *cs)
1528 {
1529 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1530         // char to wchar_t
1531         return char_to_wchar(cs);
1532 #else
1533         // char to char
1534         return cs;
1535 #endif
1536 }
1537
1538 const char *DLL_PREFIX tchar_to_char(const _TCHAR *ts)
1539 {
1540 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1541         // wchar_t to char
1542         return wchar_to_char(ts);
1543 #else
1544         // char to char
1545         return ts;
1546 #endif
1547 }
1548
1549 const _TCHAR *DLL_PREFIX wchar_to_tchar(const wchar_t *ws)
1550 {
1551 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1552         // wchar_t to wchar_t
1553         return ws;
1554 #else
1555         // wchar_t to char
1556         return wchar_to_char(ws);
1557 #endif
1558 }
1559
1560 const wchar_t *DLL_PREFIX tchar_to_wchar(const _TCHAR *ts)
1561 {
1562 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1563         // wchar_t to wchar_t
1564         return ts;
1565 #else
1566         // char to wchar_t
1567         return char_to_wchar(ts);
1568 #endif
1569 }
1570
1571 const _TCHAR *DLL_PREFIX create_string(const _TCHAR* format, ...)
1572 {
1573         static _TCHAR buffer[8][1024];
1574         static unsigned int table_index = 0;
1575         unsigned int output_index = (table_index++) & 7;
1576         va_list ap;
1577         
1578         va_start(ap, format);
1579         my_vstprintf_s(buffer[output_index], 1024, format, ap);
1580         va_end(ap);
1581         return (const _TCHAR *)buffer[output_index];
1582 }
1583
1584 int32_t DLL_PREFIX muldiv_s32(int32_t nNumber, int32_t nNumerator, int32_t nDenominator)
1585 {
1586         try {
1587                 int64_t tmp;
1588                 tmp  = (int64_t)nNumber;
1589                 tmp *= (int64_t)nNumerator;
1590                 tmp /= (int64_t)nDenominator;
1591                 return (int32_t)tmp;
1592         } catch(...) {
1593                 double tmp;
1594                 tmp  = (double)nNumber;
1595                 tmp *= (double)nNumerator;
1596                 tmp /= (double)nDenominator;
1597                 if(tmp < 0) {
1598                         return (int32_t)(tmp - 0.5);
1599                 } else {
1600                         return (int32_t)(tmp + 0.5);
1601                 }
1602         }
1603 }
1604
1605 uint32_t DLL_PREFIX muldiv_u32(uint32_t nNumber, uint32_t nNumerator, uint32_t nDenominator)
1606 {
1607         try {
1608                 uint64_t tmp;
1609                 tmp  = (uint64_t)nNumber;
1610                 tmp *= (uint64_t)nNumerator;
1611                 tmp /= (uint64_t)nDenominator;
1612                 return (uint32_t)tmp;
1613         } catch(...) {
1614                 double tmp;
1615                 tmp  = (double)nNumber;
1616                 tmp *= (double)nNumerator;
1617                 tmp /= (double)nDenominator;
1618                 return (uint32_t)(tmp + 0.5);
1619         }
1620 }
1621
1622 static bool _crc_initialized = false;
1623 static uint32_t _crc_table[256] = {0};
1624 static void init_crc32_table(void)
1625 {
1626         for(int i = 0; i < 256; i++) {
1627                 uint32_t c = i;
1628                 for(int j = 0; j < 8; j++) {
1629                         if(c & 1) {
1630                                 c = (c >> 1) ^ 0xedb88320;
1631                         } else {
1632                                 c >>= 1;
1633                         }
1634                 }
1635                 _crc_table[i] = c;
1636         }
1637         _crc_initialized = true;
1638 }
1639
1640 uint32_t DLL_PREFIX get_crc32(uint8_t data[], int size)
1641 {
1642         const uint32_t *table = (const uint32_t *)_crc_table;
1643         if(!_crc_initialized) {
1644                 init_crc32_table();
1645         }
1646         
1647         uint32_t c = ~0;
1648         for(int i = 0; i < size; i++) {
1649                 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
1650         }
1651         return ~c;
1652 }
1653
1654 uint32_t DLL_PREFIX calc_crc32(uint32_t seed, uint8_t data[], int size)
1655 {
1656 #if 0
1657         if(!_crc_initialized) {
1658                 init_crc32_table();
1659         }
1660         const uint32_t *table = (const uint32_t *)_crc_table;
1661
1662         uint32_t c = ~seed;
1663         for(int i = 0; i < size; i++) {
1664                 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
1665         }
1666         return ~c;
1667 #else
1668         // Calculate CRC32
1669         // Refer to : https://qiita.com/mikecat_mixc/items/e5d236e3a3803ef7d3c5
1670         static const uint32_t CRC_MAGIC_WORD = 0x04C11DB7;
1671         uint32_t crc = seed;
1672         uint8_t *ptr = data;
1673         uint8_t d;
1674         int bytes = size;
1675         bool is_overflow;
1676         for(int i = 0; i < bytes; i++) {
1677                 d = *ptr++;
1678                 for(int bit = 0; bit < 8; bit++) {
1679                         is_overflow = ((crc & 0x1) != 0);
1680                         crc = crc >> 1;
1681                         if((d & 0x01) != 0) crc = crc | 0x80000000;
1682                         if(is_overflow) crc = crc ^ ((uint32_t)~CRC_MAGIC_WORD);
1683                         d >>= 1;
1684                 }
1685         }
1686         return crc;
1687 #endif
1688 }
1689
1690 uint16_t DLL_PREFIX jis_to_sjis(uint16_t jis)
1691 {
1692         pair32_t tmp;
1693         
1694         tmp.w.l = jis - 0x2121;
1695         if(tmp.w.l & 0x100) {
1696                 tmp.w.l += 0x9e;
1697         } else {
1698                 tmp.w.l += 0x40;
1699         }
1700         if(tmp.b.l > 0x7f) {
1701                 tmp.w.l += 0x01;
1702         }
1703         tmp.b.h = (tmp.b.h >> 1) + 0x81;
1704         if(tmp.w.l >= 0xa000) {
1705                 tmp.w.l += 0x4000;
1706         }
1707         return tmp.w.l;
1708 }
1709
1710 int DLL_PREFIX decibel_to_volume(int decibel)
1711 {
1712         // +1 equals +0.5dB (same as fmgen)
1713         return (int)(1024.0 * pow(10.0, decibel / 40.0) + 0.5);
1714 }
1715
1716 int32_t DLL_PREFIX apply_volume(int32_t sample, int volume)
1717 {
1718 //      int64_t output;
1719         int32_t output;
1720         if(sample < 0) {
1721                 output = -sample;
1722                 output *= volume;
1723                 output >>= 10;
1724                 output = -output;
1725         } else {
1726                 output = sample;
1727                 output *= volume;
1728                 output >>= 10;
1729         }
1730 //      if(output > 2147483647) {
1731 //              return 2147483647;
1732 //      } else if(output < (-2147483647 - 1)) {
1733 //              return (-2147483647 - 1);
1734 //      } else {
1735 //              return (int32_t)output;
1736 //      }
1737         return output;
1738 }
1739
1740 void DLL_PREFIX get_host_time(cur_time_t* cur_time)
1741 {
1742 #ifdef _WIN32
1743         SYSTEMTIME sTime;
1744         GetLocalTime(&sTime);
1745         cur_time->year = sTime.wYear;
1746         cur_time->month = sTime.wMonth;
1747         cur_time->day = sTime.wDay;
1748         cur_time->day_of_week = sTime.wDayOfWeek;
1749         cur_time->hour = sTime.wHour;
1750         cur_time->minute = sTime.wMinute;
1751         cur_time->second = sTime.wSecond;
1752 #else
1753         time_t timer = time(NULL);
1754         struct tm *local = localtime(&timer);
1755         cur_time->year = local->tm_year + 1900;
1756         cur_time->month = local->tm_mon + 1;
1757         cur_time->day = local->tm_mday;
1758         cur_time->day_of_week = local->tm_wday;
1759         cur_time->hour = local->tm_hour;
1760         cur_time->minute = local->tm_min;
1761         cur_time->second = local->tm_sec;
1762 #endif
1763 }
1764
1765
1766
1767 void DLL_PREFIX cur_time_t::increment()
1768 {
1769         if(++second >= 60) {
1770                 second = 0;
1771                 if(++minute >= 60) {
1772                         minute = 0;
1773                         if(++hour >= 24) {
1774                                 hour = 0;
1775                                 // days in this month
1776                                 int days = 31;
1777                                 if(month == 2) {
1778                                         days = LEAP_YEAR(year) ? 29 : 28;
1779                                 } else if(month == 4 || month == 6 || month == 9 || month == 11) {
1780                                         days = 30;
1781                                 }
1782                                 if(++day > days) {
1783                                         day = 1;
1784                                         if(++month > 12) {
1785                                                 month = 1;
1786                                                 year++;
1787                                         }
1788                                 }
1789                                 if(++day_of_week >= 7) {
1790                                         day_of_week = 0;
1791                                 }
1792                         }
1793                 }
1794         }
1795 }
1796
1797 void DLL_PREFIX cur_time_t::update_year()
1798 {
1799         // 1970-2069
1800         if(year < 70) {
1801                 year += 2000;
1802         } else if(year < 100) {
1803                 year += 1900;
1804         }
1805 }
1806
1807 void DLL_PREFIX cur_time_t::update_day_of_week()
1808 {
1809         static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
1810         int y = year - (month < 3);
1811         day_of_week = (y + y / 4 - y / 100 + y / 400 + t[month - 1] + day) % 7;
1812 }
1813
1814 #define STATE_VERSION   1
1815
1816
1817 bool DLL_PREFIX cur_time_t::process_state(void *f, bool loading)
1818 {
1819         FILEIO *state_fio = (FILEIO *)f;
1820         
1821         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1822                 return false;
1823         }
1824         state_fio->StateValue(year);
1825         state_fio->StateValue(month);
1826         state_fio->StateValue(day);
1827         state_fio->StateValue(day_of_week);
1828         state_fio->StateValue(hour);
1829         state_fio->StateValue(minute);
1830         state_fio->StateValue(second);
1831         state_fio->StateValue(initialized);
1832         return true;
1833 }
1834
1835 const _TCHAR *DLL_PREFIX get_symbol(symbol_t *first_symbol, uint32_t addr)
1836 {
1837         static _TCHAR name[8][1024];
1838         static unsigned int table_index = 0;
1839         unsigned int output_index = (table_index++) & 7;
1840         
1841         if(first_symbol != NULL) {
1842                 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
1843                         if(symbol->addr == addr) {
1844                                 my_tcscpy_s(name[output_index], 1024, symbol->name);
1845                                 return name[output_index];
1846                         }
1847                 }
1848         }
1849         return NULL;
1850 }
1851
1852 const _TCHAR *DLL_PREFIX get_value_or_symbol(symbol_t *first_symbol, const _TCHAR *format, uint32_t addr)
1853 {
1854         static _TCHAR name[8][1024];
1855         static unsigned int table_index = 0;
1856         unsigned int output_index = (table_index++) & 7;
1857         
1858         if(first_symbol != NULL) {
1859                 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
1860                         if(symbol->addr == addr) {
1861                                 my_tcscpy_s(name[output_index], 1024, symbol->name);
1862                                 return name[output_index];
1863                         }
1864                 }
1865         }
1866         my_stprintf_s(name[output_index], 1024, format, addr);
1867         return name[output_index];
1868 }
1869
1870 const _TCHAR *DLL_PREFIX get_value_and_symbol(symbol_t *first_symbol, const _TCHAR *format, uint32_t addr)
1871 {
1872         static _TCHAR name[8][1024];
1873         static unsigned int table_index = 0;
1874         unsigned int output_index = (table_index++) & 7;
1875         
1876         my_stprintf_s(name[output_index], 1024, format, addr);
1877         
1878         if(first_symbol != NULL) {
1879                 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
1880                         if(symbol->addr == addr) {
1881                                 _TCHAR temp[1024];
1882 //                              my_stprintf_s(temp, 1024, _T(" (%s)"), symbol->name);
1883                                 my_stprintf_s(temp, 1024, _T(";%s"), symbol->name);
1884                                 my_tcscat_s(name[output_index], 1024, temp);
1885                                 return name[output_index];
1886                         }
1887                 }
1888         }
1889         return name[output_index];
1890 }
1891
1892 // Use this before writing wav_data.
1893 bool DLL_PREFIX write_dummy_wav_header(void *__fio)
1894 {
1895         if(__fio == NULL) return false;
1896
1897         FILEIO *fio = (FILEIO *)__fio;
1898         uint8_t dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];
1899
1900         if(!fio->IsOpened()) return false;
1901         
1902         memset(dummy, 0, sizeof(dummy));
1903         fio->Fwrite(dummy, sizeof(dummy), 1);
1904         return true;
1905 }
1906 // Use this after writing wav_data.
1907 bool DLL_PREFIX set_wav_header(wav_header_t *header, wav_chunk_t *first_chunk, uint16_t channels, uint32_t rate,
1908                                                            uint16_t bits, size_t file_length)
1909 {
1910         uint32_t length = (uint32_t) file_length;
1911         
1912         if(header == NULL) return false;
1913         if(first_chunk == NULL) return false;
1914
1915         pair32_t __riff_chunk_size;
1916         pair32_t __fmt_chunk_size;
1917         pair32_t __wav_chunk_size;
1918         pair16_t __fmt_id;
1919         pair16_t __channels;
1920         pair32_t __sample_rate;
1921         pair32_t __data_speed;
1922         pair16_t __block_size;
1923         pair16_t __sample_bits;
1924
1925         __riff_chunk_size.d = length - 8;
1926         __fmt_chunk_size.d = 16;
1927         __fmt_id.u16 = 1;
1928         __channels.u16 = channels;
1929         __sample_rate.d = rate;
1930         __block_size.u16 = (uint16_t)((channels * bits) / 8);
1931         __sample_bits.u16 = bits;
1932         __data_speed.d = rate * (uint32_t)(__block_size.u16);
1933
1934         memcpy(&(header->riff_chunk.id), "RIFF", 4);
1935         header->riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
1936         
1937         memcpy(&(header->wave), "WAVE", 4);
1938         memcpy(&(header->fmt_chunk.id), "fmt ", 4);
1939         header->fmt_chunk.size = __fmt_chunk_size.get_4bytes_le_to();
1940         header->format_id = __fmt_id.get_2bytes_le_to();
1941         header->channels = __channels.get_2bytes_le_to();
1942         header->sample_rate = __sample_rate.get_4bytes_le_to();
1943         header->data_speed =  __data_speed.get_4bytes_le_to();
1944         header->block_size = __block_size.get_2bytes_le_to();
1945         header->sample_bits = __sample_bits.get_2bytes_le_to();
1946
1947         memcpy(&(first_chunk->id), "data", 4);
1948         __wav_chunk_size.d = length - sizeof(wav_header_t) - sizeof(wav_chunk_t);
1949         first_chunk->size = __wav_chunk_size.get_4bytes_le_to();
1950
1951         return true;
1952 }
1953 // Note: buffers are allocated by this, You should free() within user class.
1954 bool DLL_PREFIX load_wav_to_stereo(void *__fio, int16_t **left_buf, int16_t **right_buf, uint32_t *rate, int *got_samples)
1955 {
1956
1957         if(__fio == NULL) return false;
1958         if(left_buf == NULL) return false;
1959         if(right_buf == NULL) return false;
1960         if(rate == NULL) return false;
1961         if(got_samples == NULL) return false;
1962         //if((bits != 8) && (bits != 16) && (bits != 32)) return false;
1963
1964         FILEIO *fio = (FILEIO *)__fio;
1965         if(!fio->IsOpened()) return false;
1966
1967         
1968         int16_t *left_buffer = NULL;
1969         int16_t *right_buffer = NULL;
1970         size_t samples = 0;
1971         uint32_t sample_rate = 0;
1972         
1973         wav_header_t header;
1974         wav_chunk_t  chunk;
1975
1976         pair16_t __fmt_id;
1977         pair16_t __sample_bits;
1978         pair16_t __channels;
1979         pair32_t __sample_rate;
1980         pair32_t __chunk_size;
1981
1982         fio->Fread(&header, sizeof(header), 1);
1983         __fmt_id.set_2bytes_le_from(header.format_id);
1984         __sample_bits.set_2bytes_le_from(header.sample_bits);
1985         __chunk_size.set_4bytes_le_from(header.fmt_chunk.size);
1986         __channels.set_2bytes_le_from(header.channels);
1987         __sample_rate.set_4bytes_le_from(header.sample_rate);
1988
1989         if((__fmt_id.u16 == 1) && ((__sample_bits.u16 == 8) || (__sample_bits.u16 == 16) || (__sample_bits.u16 == 32))) {
1990                 fio->Fseek(__chunk_size.d - 16, FILEIO_SEEK_CUR);
1991                 bool is_eof = false;
1992                 while(1) {
1993                         if(fio->Fread(&chunk, sizeof(chunk), 1) != 1) {
1994                                 is_eof = true;
1995                                 break;
1996                         }
1997                         __chunk_size.set_4bytes_le_from(chunk.size);
1998                         if(strncmp(chunk.id, "data", 4) == 0) {
1999                                 break;
2000                         }
2001                         fio->Fseek(__chunk_size.d, FILEIO_SEEK_CUR);
2002                 }
2003                 __chunk_size.set_4bytes_le_from(chunk.size);
2004                 if(is_eof) {
2005                         fio->Fclose();
2006                         delete fio;
2007                         return false;
2008                 }
2009                 
2010                 samples = (size_t)(__chunk_size.d / __channels.u16);
2011                 int16_t data_l, data_r;
2012                 union {
2013                         int16_t s16;
2014                         struct {
2015                                 uint8_t l, h;
2016                         } b;
2017                 } pair16;
2018                 union {
2019                         int32_t s32;
2020                         struct {
2021                                 uint8_t l, h, h2, h3;
2022                         } b;
2023                 } pair32;
2024                 
2025                 if(samples > 0) {
2026                         if(__sample_bits.u16 == 16) {
2027                                 samples /= 2;
2028                         } else if(__sample_bits.u16 == 32) {
2029                                 samples /= 4;
2030                         }
2031                         if(samples == 0) return false;
2032                         sample_rate = __sample_rate.d;
2033
2034                         left_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
2035                         right_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
2036                         if(left_buffer == NULL) {
2037                                 if(right_buffer != NULL) free(right_buffer);
2038                                 return false;
2039                         }
2040                         if(right_buffer == NULL) {
2041                                 if(left_buffer != NULL) free(left_buffer);
2042                                 return false;
2043                         }
2044                         switch(__sample_bits.u16) {
2045                         case 8:
2046                                 if(__channels.s16 == 1) {
2047                                         for(int i = 0; i < samples; i++) {
2048                                                 data_l = (int16_t)(fio->FgetUint8());
2049                                                 data_l = (data_l - 128) * 256;
2050                                                 left_buffer[i] = data_l;
2051                                                 right_buffer[i] = data_l;
2052                                         }
2053                                 } else if(__channels.s16 == 2) {
2054                                         for(int i = 0; i < samples; i++) {
2055                                                 data_l = (int16_t)(fio->FgetUint8());
2056                                                 data_l = (data_l - 128) * 256;
2057                                                 data_r = (int16_t)(fio->FgetUint8());
2058                                                 data_r = (data_r - 128) * 256;
2059                                                 left_buffer[i] = data_l;
2060                                                 right_buffer[i] = data_r;
2061                                         }
2062                                 }
2063                                 break;
2064                         case 16:
2065                                 if(__channels.s16 == 1) {
2066                                         for(int i = 0; i < samples; i++) {
2067                                                 pair16.b.l = fio->FgetUint8();
2068                                                 pair16.b.h = fio->FgetUint8();
2069                                                 data_l = pair16.s16;
2070                                                 
2071                                                 left_buffer[i] = data_l;
2072                                                 right_buffer[i] = data_l;
2073                                         }
2074                                 } else if(__channels.s16 == 2) {
2075                                         for(int i = 0; i < samples; i++) {
2076                                                 pair16.b.l = fio->FgetUint8();
2077                                                 pair16.b.h = fio->FgetUint8();
2078                                                 data_l = pair16.s16;
2079                                                 
2080                                                 pair16.b.l = fio->FgetUint8();
2081                                                 pair16.b.h = fio->FgetUint8();
2082                                                 data_r = pair16.s16;
2083                                                 left_buffer[i] = data_l;
2084                                                 right_buffer[i] = data_r;
2085                                         }
2086                                 }
2087                                 break;
2088                         case 32:
2089                                 if(__channels.s16 == 1) {
2090                                         for(int i = 0; i < samples; i++) {
2091                                                 pair32.b.l = fio->FgetUint8();
2092                                                 pair32.b.h = fio->FgetUint8();
2093                                                 pair32.b.h2 = fio->FgetUint8();
2094                                                 pair32.b.h3 = fio->FgetUint8();
2095                                                 data_l = (int16_t)(pair32.s32 / 65536);
2096                                                 
2097                                                 left_buffer[i] = data_l;
2098                                                 right_buffer[i] = data_l;
2099                                         }
2100                                 } else if(__channels.s16 == 2) {
2101                                         for(int i = 0; i < samples; i++) {
2102                                                 pair32.b.l = fio->FgetUint8();
2103                                                 pair32.b.h = fio->FgetUint8();
2104                                                 pair32.b.h2 = fio->FgetUint8();
2105                                                 pair32.b.h3 = fio->FgetUint8();
2106                                                 data_l = (int16_t)(pair32.s32 / 65536);
2107                                                 
2108                                                 pair32.b.l = fio->FgetUint8();
2109                                                 pair32.b.h = fio->FgetUint8();
2110                                                 pair32.b.h2 = fio->FgetUint8();
2111                                                 pair32.b.h3 = fio->FgetUint8();
2112                                                 data_r = (int16_t)(pair32.s32 / 65536);
2113                                                 
2114                                                 left_buffer[i] = data_l;
2115                                                 right_buffer[i] = data_r;
2116                                         }
2117                                 }
2118                                 break;
2119                         default:
2120                                 break;
2121                         }
2122                 }
2123         } else {
2124                 return false;
2125         }
2126         *left_buf = left_buffer;
2127         *right_buf = right_buffer;
2128         *rate = sample_rate;
2129         *got_samples = (int)samples;
2130         return true;
2131 }
2132
2133 bool DLL_PREFIX load_wav_to_monoral(void *__fio, int16_t **buffer, uint32_t *rate, int *got_samples)
2134 {
2135
2136         if(__fio == NULL) return false;
2137         if(buffer == NULL) return false;
2138         if(rate == NULL) return false;
2139         if(got_samples == NULL) return false;
2140         //if((bits != 8) && (bits != 16) && (bits != 32)) return false;
2141
2142         FILEIO *fio = (FILEIO *)__fio;
2143         if(!fio->IsOpened()) return false;
2144
2145         
2146         int16_t *left_buffer = NULL;
2147         size_t samples = 0;
2148         uint32_t sample_rate = 0;
2149         
2150         wav_header_t header;
2151         wav_chunk_t  chunk;
2152
2153         pair16_t __fmt_id;
2154         pair16_t __sample_bits;
2155         pair16_t __channels;
2156         pair32_t __sample_rate;
2157         pair32_t __chunk_size;
2158
2159         fio->Fread(&header, sizeof(header), 1);
2160         __fmt_id.set_2bytes_le_from(header.format_id);
2161         __sample_bits.set_2bytes_le_from(header.sample_bits);
2162         __chunk_size.set_4bytes_le_from(header.fmt_chunk.size);
2163         __channels.set_2bytes_le_from(header.channels);
2164         __sample_rate.set_4bytes_le_from(header.sample_rate);
2165
2166         if((__fmt_id.u16 == 1) && ((__sample_bits.u16 == 8) || (__sample_bits.u16 == 16) || (__sample_bits.u16 == 32))) {
2167                 fio->Fseek(__chunk_size.d - 16, FILEIO_SEEK_CUR);
2168                 bool is_eof = false;
2169                 while(1) {
2170                         if(fio->Fread(&chunk, sizeof(chunk), 1) != 1) {
2171                                 is_eof = true;
2172                                 break;
2173                         }
2174                         __chunk_size.set_4bytes_le_from(chunk.size);
2175                         if(strncmp(chunk.id, "data", 4) == 0) {
2176                                 break;
2177                         }
2178                         fio->Fseek(__chunk_size.d, FILEIO_SEEK_CUR);
2179                 }
2180                 __chunk_size.set_4bytes_le_from(chunk.size);
2181                 if(is_eof) {
2182                         fio->Fclose();
2183                         delete fio;
2184                         return false;
2185                 }
2186                 
2187                 samples = (size_t)(__chunk_size.d / __channels.u16);
2188                 int16_t data_l, data_r;
2189                 int32_t data32_l, data32_r;
2190                 union {
2191                         int16_t s16;
2192                         struct {
2193                                 uint8_t l, h;
2194                         } b;
2195                 } pair16;
2196                 union {
2197                         int32_t s32;
2198                         struct {
2199                                 uint8_t l, h, h2, h3;
2200                         } b;
2201                 } pair32;
2202                 
2203                 if(samples > 0) {
2204                         if(__sample_bits.u16 == 16) {
2205                                 samples /= 2;
2206                         } else if(__sample_bits.u16 == 32) {
2207                                 samples /= 4;
2208                         }
2209                         if(samples == 0) return false;
2210                         sample_rate = __sample_rate.d;
2211
2212                         left_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
2213                         if(left_buffer == NULL) {
2214                                 return false;
2215                         }
2216                         switch(__sample_bits.u16) {
2217                         case 8:
2218                                 if(__channels.s16 == 1) {
2219                                         for(int i = 0; i < samples; i++) {
2220                                                 data_l = (int16_t)(fio->FgetUint8());
2221                                                 data_l = (data_l - 128) * 256;
2222                                                 left_buffer[i] = data_l;
2223                                         }
2224                                 } else if(__channels.s16 == 2) {
2225                                         for(int i = 0; i < samples; i++) {
2226                                                 data_l = (int16_t)(fio->FgetUint8());
2227                                                 data_l = (data_l - 128) * 256;
2228                                                 data_r = (int16_t)(fio->FgetUint8());
2229                                                 data_r = (data_r - 128) * 256;
2230                                                 left_buffer[i] = (data_l + data_r) / 2;
2231                                         }
2232                                 }
2233                                 break;
2234                         case 16:
2235                                 if(__channels.s16 == 1) {
2236                                         for(int i = 0; i < samples; i++) {
2237                                                 pair16.b.l = fio->FgetUint8();
2238                                                 pair16.b.h = fio->FgetUint8();
2239                                                 data_l = pair16.s16;
2240                                                 
2241                                                 left_buffer[i] = data_l;
2242                                         }
2243                                 } else if(__channels.s16 == 2) {
2244                                         for(int i = 0; i < samples; i++) {
2245                                                 pair16.b.l = fio->FgetUint8();
2246                                                 pair16.b.h = fio->FgetUint8();
2247                                                 data_l = pair16.s16;
2248                                                 
2249                                                 pair16.b.l = fio->FgetUint8();
2250                                                 pair16.b.h = fio->FgetUint8();
2251                                                 data_r = pair16.s16;
2252                                                 left_buffer[i] = (data_l + data_r) / 2;
2253                                         }
2254                                 }
2255                                 break;
2256                         case 32:
2257                                 if(__channels.s16 == 1) {
2258                                         for(int i = 0; i < samples; i++) {
2259                                                 pair32.b.l = fio->FgetUint8();
2260                                                 pair32.b.h = fio->FgetUint8();
2261                                                 pair32.b.h2 = fio->FgetUint8();
2262                                                 pair32.b.h3 = fio->FgetUint8();
2263                                                 data_l = (int16_t)(pair32.s32 / 65536);
2264                                                 
2265                                                 left_buffer[i] = data_l;
2266                                         }
2267                                 } else if(__channels.s16 == 2) {
2268                                         for(int i = 0; i < samples; i++) {
2269                                                 pair32.b.l = fio->FgetUint8();
2270                                                 pair32.b.h = fio->FgetUint8();
2271                                                 pair32.b.h2 = fio->FgetUint8();
2272                                                 pair32.b.h3 = fio->FgetUint8();
2273                                                 data32_l = pair32.s32 / 65536;
2274                                                 
2275                                                 pair32.b.l = fio->FgetUint8();
2276                                                 pair32.b.h = fio->FgetUint8();
2277                                                 pair32.b.h2 = fio->FgetUint8();
2278                                                 pair32.b.h3 = fio->FgetUint8();
2279                                                 data32_r = pair32.s32 / 65536;
2280                                                 
2281                                                 left_buffer[i] = (int16_t)((data32_l + data32_r) / 2);
2282                                         }
2283                                 }
2284                                 break;
2285                         default:
2286                                 break;
2287                         }
2288                 }
2289         } else {
2290                 return false;
2291         }
2292         *buffer = left_buffer;
2293         *rate = sample_rate;
2294         *got_samples = (int)samples;
2295         return true;
2296 }
2297
2298 DLL_PREFIX const _TCHAR *get_lib_common_version()
2299 {
2300 #if defined(__LIBEMU_UTIL_VERSION)
2301         return (const _TCHAR *)__LIBEMU_UTIL_VERSION;
2302 #else
2303         return (const _TCHAR *)"\0";
2304 #endif
2305 }