2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
13 #if !defined(__WIN32) && !defined(__WIN64)
19 #include <sys/types.h>
21 #include "csp_logger.h"
29 #pragma comment(lib, "shlwapi.lib")
37 #if defined(__MINGW32__) || defined(__MINGW64__)
38 extern DWORD GetLongPathName(LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer);
41 std::string DLL_PREFIX cpp_homedir;
42 std::string DLL_PREFIX my_procname;
43 std::string DLL_PREFIX sRssDir;
46 void DLL_PREFIX common_initialize()
48 get_initial_current_path();
51 uint32_t DLL_PREFIX EndianToLittle_DWORD(uint32_t x)
53 #if defined(__LITTLE_ENDIAN__)
57 y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
58 ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
63 uint16_t DLL_PREFIX EndianToLittle_WORD(uint16_t x)
65 #if defined(__LITTLE_ENDIAN__)
69 y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
74 uint32_t DLL_PREFIX EndianFromLittle_DWORD(uint32_t x)
76 #if defined(__LITTLE_ENDIAN__)
80 y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
81 ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
86 uint16_t DLL_PREFIX EndianFromLittle_WORD(uint16_t x)
88 #if defined(__LITTLE_ENDIAN__)
92 y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
98 uint32_t DLL_PREFIX EndianToBig_DWORD(uint32_t x)
100 #if defined(__BIG_ENDIAN__)
104 y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
105 ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
110 uint16_t DLL_PREFIX EndianToBig_WORD(uint16_t x)
112 #if defined(__BIG_ENDIAN__)
116 y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
121 uint32_t DLL_PREFIX EndianFromBig_DWORD(uint32_t x)
123 #if defined(__BIG_ENDIAN__)
127 y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
128 ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
133 uint16_t DLL_PREFIX EndianFromBig_WORD(uint16_t x)
135 #if defined(__BIG_ENDIAN__)
139 y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
145 int DLL_PREFIX max(int a, int b)
154 unsigned DLL_PREFIX int max(unsigned int a, unsigned int b)
163 unsigned DLL_PREFIX int max(unsigned int a, int b)
166 if(a > (unsigned int)b) {
173 unsigned DLL_PREFIX int max(int a, unsigned int b)
176 if((unsigned int)a > b) {
183 int DLL_PREFIX min(int a, int b)
192 int DLL_PREFIX min(unsigned int a, int b)
195 if(a > INT_MAX) return b;
204 int DLL_PREFIX min(int a, unsigned int b)
207 if(b > INT_MAX) return a;
216 unsigned int DLL_PREFIX min(unsigned int a, unsigned int b)
226 #ifndef SUPPORT_SECURE_FUNCTIONS
227 //errno_t my_tfopen_s(FILE** pFile, const _TCHAR *filename, const _TCHAR *mode)
229 // if((*pFile = _tfopen(filename, mode)) != NULL) {
236 errno_t DLL_PREFIX my_tcscat_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
238 _tcscat(strDestination, strSource);
242 errno_t DLL_PREFIX my_strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource)
244 strcpy(strDestination, strSource);
248 errno_t DLL_PREFIX my_tcscpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
250 _tcscpy(strDestination, strSource);
254 errno_t DLL_PREFIX my_strncpy_s(char *strDestination, size_t numberOfElements, const char *strSource, size_t count)
256 strncpy(strDestination, strSource, count);
260 errno_t DLL_PREFIX my_tcsncpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource, size_t count)
262 _tcsncpy(strDestination, strSource, count);
266 char *DLL_PREFIX my_strtok_s(char *strToken, const char *strDelimit, char **context)
268 return strtok(strToken, strDelimit);
271 _TCHAR *DLL_PREFIX my_tcstok_s(_TCHAR *strToken, const char *strDelimit, _TCHAR **context)
273 return _tcstok(strToken, strDelimit);
276 int DLL_PREFIX my_sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
279 va_start(ap, format);
280 int result = vsnprintf(buffer, sizeOfBuffer, format, ap);
285 int DLL_PREFIX my_swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format, ...)
288 va_start(ap, format);
289 int result = vswprintf(buffer, sizeOfBuffer, format, ap);
294 int DLL_PREFIX my_stprintf_s(_TCHAR *buffer, size_t sizeOfBuffer, const _TCHAR *format, ...)
297 va_start(ap, format);
298 int result = vsnprintf(buffer, sizeOfBuffer, format, ap);
303 int DLL_PREFIX my_vsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr)
305 return vsnprintf(buffer, numberOfElements * sizeof(char), format, argptr);
308 int DLL_PREFIX my_vstprintf_s(_TCHAR *buffer, size_t numberOfElements, const _TCHAR *format, va_list argptr)
310 return vsnprintf(buffer, numberOfElements * sizeof(_TCHAR), format, argptr);
314 //#ifdef USE_FAST_MEMCPY
316 void DLL_PREFIX *my_memcpy(void *dst, void *src, size_t len)
319 register size_t len2;
320 register uint32_t s_align = (uint32_t)(((size_t)src) & 0x1f);
321 register uint32_t d_align = (uint32_t)(((size_t)dst) & 0x1f);
324 if(len == 0) return dst;
326 return memcpy(dst, src, len);
330 #if defined(WITHOUT_UNALIGNED_SIMD)
331 // Using SIMD without un-aligned instructions.
336 register uint64_t *s64 = (uint64_t *)src;
337 register uint64_t *d64 = (uint64_t *)dst;
339 case 0: // 256 vs 256
343 for(i = 0; i < 4; i++) b64[i] = s64[i];
344 for(i = 0; i < 4; i++) d64[i] = b64[i];
350 if(len1 != 0) return memcpy(d64, s64, len1);
354 case 0x10: // 256 vs 128
358 for(i = 0; i < 4; i++) b64[i] = s64[i];
359 for(i = 0; i < 2; i++) d64[i] = b64[i];
361 for(i = 2; i < 4; i++) d64[i - 2] = b64[i];
367 if(len1 != 0) return memcpy(d64, s64, len1);
372 case 0x18: // 256 vs 64
376 for(i = 0; i < 4; ++i) b64[i] = s64[i];
377 for(i = 0; i < 4; ++i) {
385 if(len1 != 0) return memcpy(d64, s64, len1);
392 case 0x1c: // 256 vs 32
395 register uint32_t *s32 = (uint32_t *)src;
396 register uint32_t *d32 = (uint32_t *)dst;
399 for(i = 0; i < 8; ++i) b32[i] = s32[i];
420 if(len1 != 0) return memcpy(d32, s32, len1);
425 return memcpy(dst, src, len1);
430 case 0x10: // Src alignn to 16.
433 register uint32_t *s32 = (uint32_t *)src;
434 register uint32_t *d32 = (uint32_t *)dst;
436 case 0: // 128 vs 256/128
441 for(i = 0; i < 4; i++) b32[i] = s32[i];
442 for(i = 0; i < 4; i++) d32[i] = b32[i];
448 if(len1 != 0) return memcpy(d32, s32, len1);
453 case 0x18: // 128 vs 64
457 for(i = 0; i < 4; ++i) b32[i] = s32[i];
458 for(i = 0; i < 2; ++i) {
462 for(i = 2; i < 4; ++i) {
470 if(len1 != 0) return memcpy(d32, s32, len1);
477 case 0x1c: // 128 vs 32
481 for(i = 0; i < 4; ++i) b32[i] = s32[i];
494 if(len1 != 0) return memcpy(d32, s32, len1);
499 return memcpy(dst, src, len1);
505 case 0x18: // Src alignn to 64.
507 register uint32_t *s32 = (uint32_t *)src;
508 register uint32_t *d32 = (uint32_t *)dst;
509 register uint64_t *s64 = (uint64_t *)src;
510 register uint64_t *d64 = (uint64_t *)dst;
513 case 0x10: // 64 vs 128
522 for(i = 0; i < 2; i++) d64[i] = b128[i];
527 if(len1 != 0) return memcpy(d64, s64, len1);
532 case 0x18: // 64 vs 64
542 if(len1 != 0) return memcpy(d64, s64, len1);
547 case 0x0c: // 64 vs 32
549 case 0x1c: // 64 vs 32
554 for(i = 0; i < 2; ++i) b32[i] = s32[i];
562 if(len1 != 0) return memcpy(d32, s32, len1);
567 return memcpy(dst, src, len1);
574 case 0x1c: // Src align 32
576 register uint32_t *s32 = (uint32_t *)src;
577 register uint32_t *d32 = (uint32_t *)dst;
578 register uint64_t *d64 = (uint64_t *)dst;
581 case 0x10: // 32 vs 128
594 for(i = 0; i < 4; i++) d32[i] = b128[i];
599 if(len1 != 0) return memcpy(d32, s32, len1);
604 case 0x18: // 32 vs 64
614 for(i = 0; i < 2; i++) d32[i] = b64[i];
619 if(len1 != 0) return memcpy(d32, s32, len1);
626 case 0x1c: // 32 vs 32
636 if(len1 != 0) return memcpy(d32, s32, len1);
641 return memcpy(dst, src, len1);
647 if(len1 != 0) return memcpy(dst, src, len1);
652 // Using SIMD *with* un-aligned instructions.
653 register uint32_t *s32 = (uint32_t *)src;
654 register uint32_t *d32 = (uint32_t *)dst;
655 if(((s_align & 0x07) != 0x0) && ((d_align & 0x07) != 0x0)) { // None align.
656 return memcpy(dst, src, len);
658 if((s_align == 0x0) || (d_align == 0x0)) { // Align to 256bit
662 for(i = 0; i < 8; i++) b256[i] = s32[i];
663 for(i = 0; i < 8; i++) d32[i] = b256[i];
669 if(len1 != 0) return memcpy(d32, s32, len1);
672 if(((s_align & 0x0f) == 0x0) || ((d_align & 0x0f) == 0x0)) { // Align to 128bit
676 for(i = 0; i < 4; i++) b128[i] = s32[i];
677 for(i = 0; i < 4; i++) d32[i] = b128[i];
683 if(len1 != 0) return memcpy(d32, s32, len1);
686 if(((s_align & 0x07) == 0x0) || ((d_align & 0x07) == 0x0)) { // Align to 64bit
690 for(i = 0; i < 2; i++) b64[i] = s32[i];
691 for(i = 0; i < 2; i++) d32[i] = b64[i];
697 if(len1 != 0) return memcpy(d32, s32, len1);
700 //if(len1 != 0) return memcpy(dst, src, len1);
709 BOOL DLL_PREFIX MyWritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName)
712 FILEIO* fio_i = new FILEIO();
713 if(fio_i->Fopen(lpFileName, FILEIO_READ_ASCII)) {
714 char tmp_path[_MAX_PATH];
715 my_sprintf_s(tmp_path, _MAX_PATH, "%s.$$$", lpFileName);
716 FILEIO* fio_o = new FILEIO();
717 if(fio_o->Fopen(tmp_path, FILEIO_WRITE_ASCII)) {
718 bool in_section = false;
719 char section[1024], line[1024], *equal;
720 my_sprintf_s(section, 1024, "[%s]", lpAppName);
721 while(fio_i->Fgets(line, 1024) != NULL && strlen(line) > 0) {
722 if(line[strlen(line) - 1] == '\n') {
723 line[strlen(line) - 1] = '\0';
728 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
730 } else if(strcmp(line, section) == 0) {
733 } else if(in_section && (equal = strstr(line, "=")) != NULL) {
735 if(strcmp(line, lpKeyName) == 0) {
736 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
743 fio_o->Fprintf("%s\n", line);
747 fio_o->Fprintf("[%s]\n", lpAppName);
749 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
757 if(!(FILEIO::RemoveFile(lpFileName) && FILEIO::RenameFile(tmp_path, lpFileName))) {
762 FILEIO* fio_o = new FILEIO();
763 if(fio_o->Fopen(lpFileName, FILEIO_WRITE_ASCII)) {
764 fio_o->Fprintf("[%s]\n", lpAppName);
765 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
775 DWORD DLL_PREFIX MyGetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName)
777 _TCHAR *lpp = (_TCHAR *)lpReturnedString;
778 if(lpDefault != NULL) {
779 my_strcpy_s(lpp, nSize, lpDefault);
783 FILEIO* fio = new FILEIO();
784 if(fio->Fopen(lpFileName, FILEIO_READ_ASCII)) {
785 bool in_section = false;
786 char section[1024], line[1024], *equal;
787 my_sprintf_s(section, 1024, "[%s]", lpAppName);
788 while(fio->Fgets(line, 1024) != NULL && strlen(line) > 0) {
789 if(line[strlen(line) - 1] == '\n') {
790 line[strlen(line) - 1] = '\0';
795 } else if(strcmp(line, section) == 0) {
798 } else if(in_section && (equal = strstr(line, "=")) != NULL) {
800 if(strcmp(line, lpKeyName) == 0) {
801 my_strcpy_s(lpp, nSize, equal + 1);
809 //csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Try App: %s Key: %s", lpAppName, lpKeyName);
813 UINT DLL_PREFIX MyGetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName)
819 memset(sstr, 0x00, sizeof(sstr));
820 memset(sval, 0x00, sizeof(sval));
821 snprintf(sval, 128, "%d", nDefault);
822 MyGetPrivateProfileString(lpAppName,lpKeyName, sval, sstr, 128, lpFileName);
828 i = strtol(s.c_str(), NULL, 10);
830 //csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_GENERAL, "Got Int: %d\n", i);
836 scrntype_t DLL_PREFIX RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
838 scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
839 scrntype_t gg = ((scrntype_t)g * 0x1f) / 0xff;
840 scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
841 return (rr << 10) | (gg << 5) | bb;
844 scrntype_t DLL_PREFIX RGBA_COLOR(uint32_t r, uint32_t g, uint b, uint32_t a)
846 return RGB_COLOR(r, g, b);
849 uint8_t DLL_PREFIX R_OF_COLOR(scrntype_t c)
851 c = (c >> 10) & 0x1f;
852 c = (c * 0xff) / 0x1f;
856 uint8_t DLL_PREFIX G_OF_COLOR(scrntype_t c)
859 c = (c * 0xff) / 0x1f;
863 uint8_t DLL_PREFIX B_OF_COLOR(scrntype_t c)
866 c = (c * 0xff) / 0x1f;
870 uint8_t DLL_PREFIX A_OF_COLOR(scrntype_t c)
874 #elif defined(_RGB565)
875 scrntype_t DLL_PREFIX RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
877 scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
878 scrntype_t gg = ((scrntype_t)g * 0x3f) / 0xff;
879 scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
880 return (rr << 11) | (gg << 5) | bb;
883 scrntype_t DLL_PREFIX RGBA_COLOR(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
885 return RGB_COLOR(r, g, b);
888 uint8_t DLL_PREFIX R_OF_COLOR(scrntype_t c)
890 c = (c >> 11) & 0x1f;
891 c = (c * 0xff) / 0x1f;
895 uint8_t DLL_PREFIX G_OF_COLOR(scrntype_t c)
898 c = (c * 0xff) / 0x3f;
902 uint8_t DLL_PREFIX B_OF_COLOR(scrntype_t c)
905 c = (c * 0xff) / 0x1f;
909 uint8_t DLL_PREFIX A_OF_COLOR(scrntype_t c)
916 struct to_upper { // Refer from documentation of libstdc++, GCC5.
917 char operator() (char c) const { return std::toupper(c); }
922 static void _my_mkdir(std::string t_dir)
925 //#if !defined(__WIN32) && !defined(__WIN64)
926 // if(fstatat(AT_FDCWD, csppath.c_str(), &st, 0) != 0) {
927 // mkdirat(AT_FDCWD, t_dir.c_str(), 0700); // Not found
930 if(stat(t_dir.c_str(), &st) != 0) {
931 QDir dir = QDir::current();
932 dir.mkdir(QString::fromStdString(t_dir));
933 //dir.mkpath(QString::fromUtf8(app_path));
936 if(stat(csppath.c_str(), &st) != 0) {
937 _mkdir(t_dir.c_str()); // Not found
943 const _TCHAR *DLL_PREFIX get_application_path()
945 static _TCHAR app_path[_MAX_PATH];
946 static bool initialized = false;
949 #if defined(_WIN32) && !defined(_USE_QT)
950 _TCHAR tmp_path[_MAX_PATH], *ptr = NULL;
951 if(GetModuleFileName(NULL, tmp_path, _MAX_PATH) != 0 && GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr) != 0 && ptr != NULL) {
954 my_tcscpy_s(app_path, _MAX_PATH, _T(".\\"));
957 #if defined(Q_OS_WIN)
958 std::string delim = "\\";
960 std::string delim = "/";
962 std::string csppath = cpp_homedir + "CommonSourceCodeProject" + delim ;
965 std::string cpath = csppath + my_procname + delim;
967 strncpy(app_path, cpath.c_str(), _MAX_PATH - 1);
971 return (const _TCHAR *)app_path;
974 const _TCHAR *DLL_PREFIX get_initial_current_path()
976 static _TCHAR current_path[_MAX_PATH];
977 static bool initialized = false;
980 #if defined(_WIN32) && !defined(_USE_QT)
981 GetCurrentDirectoryA(_MAX_PATH, current_path);
983 getcwd(current_path, _MAX_PATH);
985 int len = strlen(current_path);
986 if(current_path[len - 1] != '\\' && current_path[len - 1] != '/') {
987 #if defined(_WIN32) || defined(Q_OS_WIN)
988 current_path[len] = '\\';
990 current_path[len] = '/';
992 current_path[len + 1] = '\0';
997 return (const _TCHAR *)current_path;
1000 const _TCHAR *DLL_PREFIX create_local_path(const _TCHAR *format, ...)
1002 static _TCHAR file_path[8][_MAX_PATH];
1003 static unsigned int table_index = 0;
1004 unsigned int output_index = (table_index++) & 7;
1005 _TCHAR file_name[_MAX_PATH];
1006 //printf("%d %d\n", table_index, output_index);
1009 va_start(ap, format);
1010 my_vstprintf_s(file_name, _MAX_PATH, format, ap);
1012 my_stprintf_s(file_path[output_index], _MAX_PATH, _T("%s%s"), get_application_path(), file_name);
1013 return (const _TCHAR *)file_path[output_index];
1016 void DLL_PREFIX create_local_path(_TCHAR *file_path, int length, const _TCHAR *format, ...)
1018 _TCHAR file_name[_MAX_PATH];
1021 va_start(ap, format);
1022 my_vstprintf_s(file_name, _MAX_PATH, format, ap);
1024 my_stprintf_s(file_path, length, _T("%s%s"), get_application_path(), file_name);
1027 bool DLL_PREFIX is_absolute_path(const _TCHAR *file_path)
1030 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(':')) {
1034 return (_tcslen(file_path) > 1 && (file_path[0] == _T('/') || file_path[0] == _T('\\')));
1037 const _TCHAR *DLL_PREFIX create_date_file_path(const _TCHAR *extension)
1039 cur_time_t cur_time;
1041 get_host_time(&cur_time);
1042 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);
1045 void DLL_PREFIX create_date_file_path(_TCHAR *file_path, int length, const _TCHAR *extension)
1047 my_tcscpy_s(file_path, length, create_date_file_path(extension));
1050 bool DLL_PREFIX check_file_extension(const _TCHAR *file_path, const _TCHAR *ext)
1052 #if defined(_USE_QT)
1053 std::string s_fpath = file_path;
1054 std::string s_ext = ext;
1057 std::transform(s_fpath.begin(), s_fpath.end(), s_fpath.begin(), to_upper());
1058 std::transform(s_ext.begin(), s_ext.end(), s_ext.begin(), to_upper());
1059 if(s_fpath.length() < s_ext.length()) return false;
1060 pos = s_fpath.rfind(s_ext.c_str(), s_fpath.length());
1061 if((pos != (int)std::string::npos) && (pos >= ((int)s_fpath.length() - (int)s_ext.length()))) return true;
1064 int nam_len = _tcslen(file_path);
1065 int ext_len = _tcslen(ext);
1067 return (nam_len >= ext_len && _tcsncicmp(&file_path[nam_len - ext_len], ext, ext_len) == 0);
1071 const _TCHAR *DLL_PREFIX get_file_path_without_extensiton(const _TCHAR *file_path)
1073 static _TCHAR path[8][_MAX_PATH];
1074 static unsigned int table_index = 0;
1075 unsigned int output_index = (table_index++) & 7;
1077 my_tcscpy_s(path[output_index], _MAX_PATH, file_path);
1078 #if defined(_WIN32) && defined(_MSC_VER)
1079 PathRemoveExtension(path[output_index]);
1080 #elif defined(_USE_QT)
1082 delim = QString::fromUtf8(".");
1083 QString tmp_path = QString::fromUtf8(file_path);
1084 int n = tmp_path.lastIndexOf(delim);
1086 tmp_path = tmp_path.left(n);
1088 //printf("%s\n", tmp_path.toUtf8().constData());
1089 memset(path[output_index], 0x00, sizeof(_TCHAR) * _MAX_PATH);
1090 strncpy(path[output_index], tmp_path.toUtf8().constData(), _MAX_PATH - 1);
1093 return (const _TCHAR *)path[output_index];
1096 void DLL_PREFIX get_long_full_path_name(const _TCHAR* src, _TCHAR* dst, size_t dst_len)
1099 _TCHAR tmp[_MAX_PATH];
1100 if(GetFullPathName(src, _MAX_PATH, tmp, NULL) == 0) {
1101 my_tcscpy_s(dst, dst_len, src);
1102 } else if(GetLongPathName(tmp, dst, _MAX_PATH) == 0) {
1103 my_tcscpy_s(dst, dst_len, tmp);
1105 #elif defined(_USE_QT)
1106 QString tmp_path = QString::fromUtf8(src);
1107 QFileInfo info(tmp_path);
1108 my_tcscpy_s(dst, dst_len, info.absoluteFilePath().toLocal8Bit().constData());
1110 // write code for your environment
1115 const _TCHAR *DLL_PREFIX get_parent_dir(const _TCHAR* file)
1117 static _TCHAR path[8][_MAX_PATH];
1118 static unsigned int table_index = 0;
1119 unsigned int output_index = (table_index++) & 7;
1123 GetFullPathName(file, _MAX_PATH, path[output_index], &ptr);
1127 #elif defined(_USE_QT)
1129 #if defined(Q_OS_WIN)
1130 delim = QString::fromUtf8("\\");
1132 delim = QString::fromUtf8("/");
1134 QString tmp_path = QString::fromUtf8(file);
1135 int n = tmp_path.lastIndexOf(delim);
1137 tmp_path = tmp_path.left(n);
1138 tmp_path.append(delim);
1140 //printf("%s\n", tmp_path.toUtf8().constData());
1141 memset(path[output_index], 0x00, sizeof(_TCHAR) * _MAX_PATH);
1142 strncpy(path[output_index], tmp_path.toUtf8().constData(), _MAX_PATH - 1);
1144 // write code for your environment
1146 return path[output_index];
1149 const wchar_t *DLL_PREFIX char_to_wchar(const char *cs)
1152 static wchar_t ws[4096];
1154 #if defined(_WIN32) || defined(_USE_QT)
1155 mbstowcs(ws, cs, strlen(cs));
1157 // write code for your environment
1162 const char *DLL_PREFIX wchar_to_char(const wchar_t *ws)
1165 static char cs[4096];
1168 wcstombs(cs, ws, wcslen(ws));
1169 #elif defined(_USE_QT)
1170 wcstombs(cs, ws, wcslen(ws));
1172 // write code for your environment
1177 const _TCHAR *DLL_PREFIX char_to_tchar(const char *cs)
1179 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1181 return char_to_wchar(cs);
1188 const char *DLL_PREFIX tchar_to_char(const _TCHAR *ts)
1190 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1192 return wchar_to_char(ts);
1199 const _TCHAR *DLL_PREFIX wchar_to_tchar(const wchar_t *ws)
1201 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1202 // wchar_t to wchar_t
1206 return wchar_to_char(ws);
1210 const wchar_t *DLL_PREFIX tchar_to_wchar(const _TCHAR *ts)
1212 #if defined(_UNICODE) && defined(SUPPORT_TCHAR_TYPE)
1213 // wchar_t to wchar_t
1217 return char_to_wchar(ts);
1221 const _TCHAR *DLL_PREFIX create_string(const _TCHAR* format, ...)
1223 static _TCHAR buffer[8][1024];
1224 static unsigned int table_index = 0;
1225 unsigned int output_index = (table_index++) & 7;
1228 va_start(ap, format);
1229 my_vstprintf_s(buffer[output_index], 1024, format, ap);
1231 return (const _TCHAR *)buffer[output_index];
1234 int32_t DLL_PREFIX muldiv_s32(int32_t nNumber, int32_t nNumerator, int32_t nDenominator)
1238 tmp = (int64_t)nNumber;
1239 tmp *= (int64_t)nNumerator;
1240 tmp /= (int64_t)nDenominator;
1241 return (int32_t)tmp;
1244 tmp = (double)nNumber;
1245 tmp *= (double)nNumerator;
1246 tmp /= (double)nDenominator;
1248 return (int32_t)(tmp - 0.5);
1250 return (int32_t)(tmp + 0.5);
1255 uint32_t DLL_PREFIX muldiv_u32(uint32_t nNumber, uint32_t nNumerator, uint32_t nDenominator)
1259 tmp = (uint64_t)nNumber;
1260 tmp *= (uint64_t)nNumerator;
1261 tmp /= (uint64_t)nDenominator;
1262 return (uint32_t)tmp;
1265 tmp = (double)nNumber;
1266 tmp *= (double)nNumerator;
1267 tmp /= (double)nDenominator;
1268 return (uint32_t)(tmp + 0.5);
1272 static bool _crc_initialized = false;
1273 static uint32_t _crc_table[256] = {0};
1274 static void init_crc32_table(void)
1276 for(int i = 0; i < 256; i++) {
1278 for(int j = 0; j < 8; j++) {
1280 c = (c >> 1) ^ 0xedb88320;
1287 _crc_initialized = true;
1290 uint32_t DLL_PREFIX get_crc32(uint8_t data[], int size)
1292 const uint32_t *table = (const uint32_t *)_crc_table;
1293 if(!_crc_initialized) {
1298 for(int i = 0; i < size; i++) {
1299 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
1304 uint32_t DLL_PREFIX calc_crc32(uint32_t seed, uint8_t data[], int size)
1307 if(!_crc_initialized) {
1310 const uint32_t *table = (const uint32_t *)_crc_table;
1313 for(int i = 0; i < size; i++) {
1314 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
1319 // Refer to : https://qiita.com/mikecat_mixc/items/e5d236e3a3803ef7d3c5
1320 static const uint32_t CRC_MAGIC_WORD = 0x04C11DB7;
1321 uint32_t crc = seed;
1322 uint8_t *ptr = data;
1326 for(int i = 0; i < bytes; i++) {
1328 for(int bit = 0; bit < 8; bit++) {
1329 is_overflow = ((crc & 0x1) != 0);
1331 if((d & 0x01) != 0) crc = crc | 0x80000000;
1332 if(is_overflow) crc = crc ^ ((uint32_t)~CRC_MAGIC_WORD);
1340 uint16_t DLL_PREFIX jis_to_sjis(uint16_t jis)
1344 tmp.w.l = jis - 0x2121;
1345 if(tmp.w.l & 0x100) {
1350 if(tmp.b.l > 0x7f) {
1353 tmp.b.h = (tmp.b.h >> 1) + 0x81;
1354 if(tmp.w.l >= 0xa000) {
1360 int DLL_PREFIX decibel_to_volume(int decibel)
1362 // +1 equals +0.5dB (same as fmgen)
1363 return (int)(1024.0 * pow(10.0, decibel / 40.0) + 0.5);
1366 int32_t DLL_PREFIX apply_volume(int32_t sample, int volume)
1380 // if(output > 2147483647) {
1381 // return 2147483647;
1382 // } else if(output < (-2147483647 - 1)) {
1383 // return (-2147483647 - 1);
1385 // return (int32_t)output;
1390 void DLL_PREFIX get_host_time(cur_time_t* cur_time)
1394 GetLocalTime(&sTime);
1395 cur_time->year = sTime.wYear;
1396 cur_time->month = sTime.wMonth;
1397 cur_time->day = sTime.wDay;
1398 cur_time->day_of_week = sTime.wDayOfWeek;
1399 cur_time->hour = sTime.wHour;
1400 cur_time->minute = sTime.wMinute;
1401 cur_time->second = sTime.wSecond;
1403 time_t timer = time(NULL);
1404 struct tm *local = localtime(&timer);
1405 cur_time->year = local->tm_year + 1900;
1406 cur_time->month = local->tm_mon + 1;
1407 cur_time->day = local->tm_mday;
1408 cur_time->day_of_week = local->tm_wday;
1409 cur_time->hour = local->tm_hour;
1410 cur_time->minute = local->tm_min;
1411 cur_time->second = local->tm_sec;
1417 void DLL_PREFIX cur_time_t::increment()
1419 if(++second >= 60) {
1421 if(++minute >= 60) {
1425 // days in this month
1428 days = LEAP_YEAR(year) ? 29 : 28;
1429 } else if(month == 4 || month == 6 || month == 9 || month == 11) {
1439 if(++day_of_week >= 7) {
1447 void DLL_PREFIX cur_time_t::update_year()
1452 } else if(year < 100) {
1457 void DLL_PREFIX cur_time_t::update_day_of_week()
1459 static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
1460 int y = year - (month < 3);
1461 day_of_week = (y + y / 4 - y / 100 + y / 400 + t[month - 1] + day) % 7;
1464 #define STATE_VERSION 1
1467 bool DLL_PREFIX cur_time_t::process_state(void *f, bool loading)
1469 FILEIO *state_fio = (FILEIO *)f;
1471 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1474 state_fio->StateInt32(year);
1475 state_fio->StateInt32(month);
1476 state_fio->StateInt32(day);
1477 state_fio->StateInt32(day_of_week);
1478 state_fio->StateInt32(hour);
1479 state_fio->StateInt32(minute);
1480 state_fio->StateInt32(second);
1481 state_fio->StateBool(initialized);
1485 const _TCHAR *DLL_PREFIX get_symbol(symbol_t *first_symbol, uint32_t addr)
1487 static _TCHAR name[8][1024];
1488 static unsigned int table_index = 0;
1489 unsigned int output_index = (table_index++) & 7;
1491 if(first_symbol != NULL) {
1492 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
1493 if(symbol->addr == addr) {
1494 my_tcscpy_s(name[output_index], 1024, symbol->name);
1495 return name[output_index];
1502 const _TCHAR *DLL_PREFIX get_value_or_symbol(symbol_t *first_symbol, const _TCHAR *format, uint32_t addr)
1504 static _TCHAR name[8][1024];
1505 static unsigned int table_index = 0;
1506 unsigned int output_index = (table_index++) & 7;
1508 if(first_symbol != NULL) {
1509 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
1510 if(symbol->addr == addr) {
1511 my_tcscpy_s(name[output_index], 1024, symbol->name);
1512 return name[output_index];
1516 my_stprintf_s(name[output_index], 1024, format, addr);
1517 return name[output_index];
1520 const _TCHAR *DLL_PREFIX get_value_and_symbol(symbol_t *first_symbol, const _TCHAR *format, uint32_t addr)
1522 static _TCHAR name[8][1024];
1523 static unsigned int table_index = 0;
1524 unsigned int output_index = (table_index++) & 7;
1526 my_stprintf_s(name[output_index], 1024, format, addr);
1528 if(first_symbol != NULL) {
1529 for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
1530 if(symbol->addr == addr) {
1532 // my_stprintf_s(temp, 1024, _T(" (%s)"), symbol->name);
1533 my_stprintf_s(temp, 1024, _T(";%s"), symbol->name);
1534 my_tcscat_s(name[output_index], 1024, temp);
1535 return name[output_index];
1539 return name[output_index];
1542 // Use this before writing wav_data.
1543 bool DLL_PREFIX write_dummy_wav_header(void *__fio)
1545 if(__fio == NULL) return false;
1547 FILEIO *fio = (FILEIO *)__fio;
1548 uint8_t dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];
1550 if(!fio->IsOpened()) return false;
1552 memset(dummy, 0, sizeof(dummy));
1553 fio->Fwrite(dummy, sizeof(dummy), 1);
1556 // Use this after writing wav_data.
1557 bool DLL_PREFIX set_wav_header(wav_header_t *header, wav_chunk_t *first_chunk, uint16_t channels, uint32_t rate,
1558 uint16_t bits, size_t file_length)
1560 uint32_t length = (uint32_t) file_length;
1562 if(header == NULL) return false;
1563 if(first_chunk == NULL) return false;
1565 pair_t __riff_chunk_size;
1566 pair_t __fmt_chunk_size;
1567 pair_t __wav_chunk_size;
1569 pair16_t __channels;
1570 pair_t __sample_rate;
1571 pair_t __data_speed;
1572 pair16_t __block_size;
1573 pair16_t __sample_bits;
1575 __riff_chunk_size.d = length - 8;
1576 __fmt_chunk_size.d = 16;
1578 __channels.u16 = channels;
1579 __sample_rate.d = rate;
1580 __block_size.u16 = (uint16_t)((channels * bits) / 8);
1581 __sample_bits.u16 = bits;
1582 __data_speed.d = rate * (uint32_t)(__block_size.u16);
1584 memcpy(&(header->riff_chunk.id), "RIFF", 4);
1585 header->riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
1587 memcpy(&(header->wave), "WAVE", 4);
1588 memcpy(&(header->fmt_chunk.id), "fmt ", 4);
1589 header->fmt_chunk.size = __fmt_chunk_size.get_4bytes_le_to();
1590 header->format_id = __fmt_id.get_2bytes_le_to();
1591 header->channels = __channels.get_2bytes_le_to();
1592 header->sample_rate = __sample_rate.get_4bytes_le_to();
1593 header->data_speed = __data_speed.get_4bytes_le_to();
1594 header->block_size = __block_size.get_2bytes_le_to();
1595 header->sample_bits = __sample_bits.get_2bytes_le_to();
1597 memcpy(&(first_chunk->id), "data", 4);
1598 __wav_chunk_size.d = length - sizeof(wav_header_t) - sizeof(wav_chunk_t);
1599 first_chunk->size = __wav_chunk_size.get_4bytes_le_to();
1603 // Note: buffers are allocated by this, You should free() within user class.
1604 bool DLL_PREFIX load_wav_to_stereo(void *__fio, int16_t **left_buf, int16_t **right_buf, uint32_t *rate, int *got_samples)
1607 if(__fio == NULL) return false;
1608 if(left_buf == NULL) return false;
1609 if(right_buf == NULL) return false;
1610 if(rate == NULL) return false;
1611 if(got_samples == NULL) return false;
1612 //if((bits != 8) && (bits != 16) && (bits != 32)) return false;
1614 FILEIO *fio = (FILEIO *)__fio;
1615 if(!fio->IsOpened()) return false;
1618 int16_t *left_buffer = NULL;
1619 int16_t *right_buffer = NULL;
1621 uint32_t sample_rate = 0;
1623 wav_header_t header;
1627 pair16_t __sample_bits;
1628 pair16_t __channels;
1629 pair_t __sample_rate;
1630 pair_t __chunk_size;
1632 fio->Fread(&header, sizeof(header), 1);
1633 __fmt_id.set_2bytes_le_from(header.format_id);
1634 __sample_bits.set_2bytes_le_from(header.sample_bits);
1635 __chunk_size.set_4bytes_le_from(header.fmt_chunk.size);
1636 __channels.set_2bytes_le_from(header.channels);
1637 __sample_rate.set_4bytes_le_from(header.sample_rate);
1639 if((__fmt_id.u16 == 1) && ((__sample_bits.u16 == 8) || (__sample_bits.u16 == 16) || (__sample_bits.u16 == 32))) {
1640 fio->Fseek(__chunk_size.d - 16, FILEIO_SEEK_CUR);
1641 bool is_eof = false;
1643 if(fio->Fread(&chunk, sizeof(chunk), 1) != 1) {
1647 __chunk_size.set_4bytes_le_from(chunk.size);
1648 if(strncmp(chunk.id, "data", 4) == 0) {
1651 fio->Fseek(__chunk_size.d, FILEIO_SEEK_CUR);
1653 __chunk_size.set_4bytes_le_from(chunk.size);
1660 samples = (size_t)(__chunk_size.d / __channels.u16);
1661 int16_t data_l, data_r;
1671 uint8_t l, h, h2, h3;
1676 if(__sample_bits.u16 == 16) {
1678 } else if(__sample_bits.u16 == 32) {
1681 if(samples == 0) return false;
1682 sample_rate = __sample_rate.d;
1684 left_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
1685 right_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
1686 if(left_buffer == NULL) {
1687 if(right_buffer != NULL) free(right_buffer);
1690 if(right_buffer == NULL) {
1691 if(left_buffer != NULL) free(left_buffer);
1694 switch(__sample_bits.u16) {
1696 if(__channels.s16 == 1) {
1697 for(int i = 0; i < samples; i++) {
1698 data_l = (int16_t)(fio->FgetUint8());
1699 data_l = (data_l - 128) * 256;
1700 left_buffer[i] = data_l;
1701 right_buffer[i] = data_l;
1703 } else if(__channels.s16 == 2) {
1704 for(int i = 0; i < samples; i++) {
1705 data_l = (int16_t)(fio->FgetUint8());
1706 data_l = (data_l - 128) * 256;
1707 data_r = (int16_t)(fio->FgetUint8());
1708 data_r = (data_r - 128) * 256;
1709 left_buffer[i] = data_l;
1710 right_buffer[i] = data_r;
1715 if(__channels.s16 == 1) {
1716 for(int i = 0; i < samples; i++) {
1717 pair16.b.l = fio->FgetUint8();
1718 pair16.b.h = fio->FgetUint8();
1719 data_l = pair16.s16;
1721 left_buffer[i] = data_l;
1722 right_buffer[i] = data_l;
1724 } else if(__channels.s16 == 2) {
1725 for(int i = 0; i < samples; i++) {
1726 pair16.b.l = fio->FgetUint8();
1727 pair16.b.h = fio->FgetUint8();
1728 data_l = pair16.s16;
1730 pair16.b.l = fio->FgetUint8();
1731 pair16.b.h = fio->FgetUint8();
1732 data_r = pair16.s16;
1733 left_buffer[i] = data_l;
1734 right_buffer[i] = data_r;
1739 if(__channels.s16 == 1) {
1740 for(int i = 0; i < samples; i++) {
1741 pair32.b.l = fio->FgetUint8();
1742 pair32.b.h = fio->FgetUint8();
1743 pair32.b.h2 = fio->FgetUint8();
1744 pair32.b.h3 = fio->FgetUint8();
1745 data_l = (int16_t)(pair32.s32 / 65536);
1747 left_buffer[i] = data_l;
1748 right_buffer[i] = data_l;
1750 } else if(__channels.s16 == 2) {
1751 for(int i = 0; i < samples; i++) {
1752 pair32.b.l = fio->FgetUint8();
1753 pair32.b.h = fio->FgetUint8();
1754 pair32.b.h2 = fio->FgetUint8();
1755 pair32.b.h3 = fio->FgetUint8();
1756 data_l = (int16_t)(pair32.s32 / 65536);
1758 pair32.b.l = fio->FgetUint8();
1759 pair32.b.h = fio->FgetUint8();
1760 pair32.b.h2 = fio->FgetUint8();
1761 pair32.b.h3 = fio->FgetUint8();
1762 data_r = (int16_t)(pair32.s32 / 65536);
1764 left_buffer[i] = data_l;
1765 right_buffer[i] = data_r;
1776 *left_buf = left_buffer;
1777 *right_buf = right_buffer;
1778 *rate = sample_rate;
1779 *got_samples = (int)samples;
1783 bool DLL_PREFIX load_wav_to_monoral(void *__fio, int16_t **buffer, uint32_t *rate, int *got_samples)
1786 if(__fio == NULL) return false;
1787 if(buffer == NULL) return false;
1788 if(rate == NULL) return false;
1789 if(got_samples == NULL) return false;
1790 //if((bits != 8) && (bits != 16) && (bits != 32)) return false;
1792 FILEIO *fio = (FILEIO *)__fio;
1793 if(!fio->IsOpened()) return false;
1796 int16_t *left_buffer = NULL;
1798 uint32_t sample_rate = 0;
1800 wav_header_t header;
1804 pair16_t __sample_bits;
1805 pair16_t __channels;
1806 pair_t __sample_rate;
1807 pair_t __chunk_size;
1809 fio->Fread(&header, sizeof(header), 1);
1810 __fmt_id.set_2bytes_le_from(header.format_id);
1811 __sample_bits.set_2bytes_le_from(header.sample_bits);
1812 __chunk_size.set_4bytes_le_from(header.fmt_chunk.size);
1813 __channels.set_2bytes_le_from(header.channels);
1814 __sample_rate.set_4bytes_le_from(header.sample_rate);
1816 if((__fmt_id.u16 == 1) && ((__sample_bits.u16 == 8) || (__sample_bits.u16 == 16) || (__sample_bits.u16 == 32))) {
1817 fio->Fseek(__chunk_size.d - 16, FILEIO_SEEK_CUR);
1818 bool is_eof = false;
1820 if(fio->Fread(&chunk, sizeof(chunk), 1) != 1) {
1824 __chunk_size.set_4bytes_le_from(chunk.size);
1825 if(strncmp(chunk.id, "data", 4) == 0) {
1828 fio->Fseek(__chunk_size.d, FILEIO_SEEK_CUR);
1830 __chunk_size.set_4bytes_le_from(chunk.size);
1837 samples = (size_t)(__chunk_size.d / __channels.u16);
1838 int16_t data_l, data_r;
1839 int32_t data32_l, data32_r;
1849 uint8_t l, h, h2, h3;
1854 if(__sample_bits.u16 == 16) {
1856 } else if(__sample_bits.u16 == 32) {
1859 if(samples == 0) return false;
1860 sample_rate = __sample_rate.d;
1862 left_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
1863 if(left_buffer == NULL) {
1866 switch(__sample_bits.u16) {
1868 if(__channels.s16 == 1) {
1869 for(int i = 0; i < samples; i++) {
1870 data_l = (int16_t)(fio->FgetUint8());
1871 data_l = (data_l - 128) * 256;
1872 left_buffer[i] = data_l;
1874 } else if(__channels.s16 == 2) {
1875 for(int i = 0; i < samples; i++) {
1876 data_l = (int16_t)(fio->FgetUint8());
1877 data_l = (data_l - 128) * 256;
1878 data_r = (int16_t)(fio->FgetUint8());
1879 data_r = (data_r - 128) * 256;
1880 left_buffer[i] = (data_l + data_r) / 2;
1885 if(__channels.s16 == 1) {
1886 for(int i = 0; i < samples; i++) {
1887 pair16.b.l = fio->FgetUint8();
1888 pair16.b.h = fio->FgetUint8();
1889 data_l = pair16.s16;
1891 left_buffer[i] = data_l;
1893 } else if(__channels.s16 == 2) {
1894 for(int i = 0; i < samples; i++) {
1895 pair16.b.l = fio->FgetUint8();
1896 pair16.b.h = fio->FgetUint8();
1897 data_l = pair16.s16;
1899 pair16.b.l = fio->FgetUint8();
1900 pair16.b.h = fio->FgetUint8();
1901 data_r = pair16.s16;
1902 left_buffer[i] = (data_l + data_r) / 2;
1907 if(__channels.s16 == 1) {
1908 for(int i = 0; i < samples; i++) {
1909 pair32.b.l = fio->FgetUint8();
1910 pair32.b.h = fio->FgetUint8();
1911 pair32.b.h2 = fio->FgetUint8();
1912 pair32.b.h3 = fio->FgetUint8();
1913 data_l = (int16_t)(pair32.s32 / 65536);
1915 left_buffer[i] = data_l;
1917 } else if(__channels.s16 == 2) {
1918 for(int i = 0; i < samples; i++) {
1919 pair32.b.l = fio->FgetUint8();
1920 pair32.b.h = fio->FgetUint8();
1921 pair32.b.h2 = fio->FgetUint8();
1922 pair32.b.h3 = fio->FgetUint8();
1923 data32_l = pair32.s32 / 65536;
1925 pair32.b.l = fio->FgetUint8();
1926 pair32.b.h = fio->FgetUint8();
1927 pair32.b.h2 = fio->FgetUint8();
1928 pair32.b.h3 = fio->FgetUint8();
1929 data32_r = pair32.s32 / 65536;
1931 left_buffer[i] = (int16_t)((data32_l + data32_r) / 2);
1942 *buffer = left_buffer;
1943 *rate = sample_rate;
1944 *got_samples = (int)samples;
1948 DLL_PREFIX const _TCHAR *get_lib_common_version()
1950 #if defined(__LIBEMU_UTIL_VERSION)
1951 return (const _TCHAR *)__LIBEMU_UTIL_VERSION;
1953 return (const _TCHAR *)"\0";