2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
13 #if !defined(__WIN32) && !defined(__WIN64)
19 #include <sys/types.h>
21 #include "agar_logger.h"
28 #pragma comment(lib, "shlwapi.lib")
36 #if defined(__MINGW32__) || defined(__MINGW64__)
37 extern DWORD GetLongPathName(LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer);
40 extern std::string cpp_homedir;
41 extern std::string my_procname;
44 uint32_t EndianToLittle_DWORD(uint32_t x)
46 #if defined(__LITTLE_ENDIAN__)
50 y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
51 ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
56 uint16_t EndianToLittle_WORD(uint16_t x)
58 #if defined(__LITTLE_ENDIAN__)
62 y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
77 unsigned int max(unsigned int a, unsigned int b)
95 unsigned int min(unsigned int a, unsigned int b)
105 #ifndef SUPPORT_SECURE_FUNCTIONS
106 //errno_t my_tfopen_s(FILE** pFile, const _TCHAR *filename, const _TCHAR *mode)
108 // if((*pFile = _tfopen(filename, mode)) != NULL) {
115 errno_t my_strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource)
117 strcpy(strDestination, strSource);
121 errno_t my_tcscpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
123 _tcscpy(strDestination, strSource);
127 errno_t my_strncpy_s(char *strDestination, size_t numberOfElements, const char *strSource, size_t count)
129 strncpy(strDestination, strSource, count);
133 errno_t my_tcsncpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource, size_t count)
135 _tcsncpy(strDestination, strSource, count);
139 char *my_strtok_s(char *strToken, const char *strDelimit, char **context)
141 return strtok(strToken, strDelimit);
144 _TCHAR *my_tcstok_s(_TCHAR *strToken, const char *strDelimit, _TCHAR **context)
146 return _tcstok(strToken, strDelimit);
149 int my_sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
152 va_start(ap, format);
153 int result = vsprintf(buffer, format, ap);
158 int my_stprintf_s(_TCHAR *buffer, size_t sizeOfBuffer, const _TCHAR *format, ...)
161 va_start(ap, format);
162 int result = _vstprintf(buffer, format, ap);
167 int my_vsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr)
169 return vsprintf(buffer, format, argptr);
172 int my_vstprintf_s(_TCHAR *buffer, size_t numberOfElements, const _TCHAR *format, va_list argptr)
174 return _vstprintf(buffer, format, argptr);
179 BOOL MyWritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName)
182 FILEIO* fio_i = new FILEIO();
183 if(fio_i->Fopen(lpFileName, FILEIO_READ_ASCII)) {
184 char tmp_path[_MAX_PATH];
185 my_sprintf_s(tmp_path, _MAX_PATH, "%s.$$$", lpFileName);
186 FILEIO* fio_o = new FILEIO();
187 if(fio_o->Fopen(tmp_path, FILEIO_WRITE_ASCII)) {
188 bool in_section = false;
189 char section[1024], line[1024], *equal;
190 my_sprintf_s(section, 1024, "[%s]", lpAppName);
191 while(fio_i->Fgets(line, 1024) != NULL && strlen(line) > 0) {
192 if(line[strlen(line) - 1] == '\n') {
193 line[strlen(line) - 1] = '\0';
198 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
200 } else if(strcmp(line, section) == 0) {
203 } else if(in_section && (equal = strstr(line, "=")) != NULL) {
205 if(strcmp(line, lpKeyName) == 0) {
206 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
213 fio_o->Fprintf("%s\n", line);
217 fio_o->Fprintf("[%s]\n", lpAppName);
219 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
227 if(!(FILEIO::RemoveFile(lpFileName) && FILEIO::RenameFile(tmp_path, lpFileName))) {
232 FILEIO* fio_o = new FILEIO();
233 if(fio_o->Fopen(lpFileName, FILEIO_WRITE_ASCII)) {
234 fio_o->Fprintf("[%s]\n", lpAppName);
235 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
244 static std::string MyGetPrivateProfileStr(const _TCHAR *lpAppName, const _TCHAR *lpKeyName, _TCHAR *lpFileName)
247 char ibuf[4096 + 102];
251 std::string::size_type pos;
254 FILEIO *pf = new FILEIO;
258 key = key + lpKeyName;
260 if(pf->Fopen(lpFileName, FILEIO_READ_ASCII) != true) {
264 AGAR_DebugLog(AGAR_LOG_DEBUG, "Try App: %s Key: %s", lpAppName, lpKeyName);
265 pf->Fseek(0, FILEIO_SEEK_SET);
272 if(l_len > (4096 + 100)) { // Too long, read dummy.
273 c = (char)pf->Fgetc();
274 if((c != EOF) && (c != '\n') && (c != '\0')) continue;
277 c = (char)pf->Fgetc();
278 if((c == EOF) || (c == '\n') || (c == '\0')) break;
286 key_str = key_str + "=";
287 pos = got_str.find(key_str);
288 if(pos != std::string::npos) break;
289 if(c == EOF) return "";
294 got_str.erase(0, pos + key_str.length());
295 AGAR_DebugLog(AGAR_LOG_DEBUG, "Got: %s Length: %d", got_str.c_str(), got_str.length());
299 DWORD MyGetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName)
301 _TCHAR *lpp = (_TCHAR *)lpReturnedString;
302 if(lpDefault != NULL) {
303 my_strcpy_s(lpp, nSize, lpDefault);
307 FILEIO* fio = new FILEIO();
308 if(fio->Fopen(lpFileName, FILEIO_READ_ASCII)) {
309 bool in_section = false;
310 char section[1024], line[1024], *equal;
311 my_sprintf_s(section, 1024, "[%s]", lpAppName);
312 while(fio->Fgets(line, 1024) != NULL && strlen(line) > 0) {
313 if(line[strlen(line) - 1] == '\n') {
314 line[strlen(line) - 1] = '\0';
319 } else if(strcmp(line, section) == 0) {
322 } else if(in_section && (equal = strstr(line, "=")) != NULL) {
324 if(strcmp(line, lpKeyName) == 0) {
325 my_strcpy_s(lpp, nSize, equal + 1);
336 UINT MyGetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName)
342 memset(sstr, 0x00, sizeof(sstr));
343 memset(sval, 0x00, sizeof(sval));
344 snprintf(sval, 128, "%d", nDefault);
345 MyGetPrivateProfileString(lpAppName,lpKeyName, sval, sstr, 128, lpFileName);
351 i = strtol(s.c_str(), NULL, 10);
353 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Got Int: %d\n", i);
359 scrntype_t RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
361 scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
362 scrntype_t gg = ((scrntype_t)g * 0x1f) / 0xff;
363 scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
364 return (rr << 10) | (gg << 5) | bb;
367 scrntype_t RGBA_COLOR(uint32_t r, uint32_t g, uint b, uint32_t a)
369 return RGB_COLOR(r, g, b);
372 uint8_t R_OF_COLOR(scrntype_t c)
374 c = (c >> 10) & 0x1f;
375 c = (c * 0xff) / 0x1f;
379 uint8_t G_OF_COLOR(scrntype_t c)
382 c = (c * 0xff) / 0x1f;
386 uint8_t B_OF_COLOR(scrntype_t c)
389 c = (c * 0xff) / 0x1f;
393 uint8_t A_OF_COLOR(scrntype_t c)
397 #elif defined(_RGB565)
398 scrntype_t RGB_COLOR(uint32_t r, uint32_t g, uint32_t b)
400 scrntype_t rr = ((scrntype_t)r * 0x1f) / 0xff;
401 scrntype_t gg = ((scrntype_t)g * 0x3f) / 0xff;
402 scrntype_t bb = ((scrntype_t)b * 0x1f) / 0xff;
403 return (rr << 11) | (gg << 5) | bb;
406 scrntype_t RGBA_COLOR(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
408 return RGB_COLOR(r, g, b);
411 uint8_t R_OF_COLOR(scrntype_t c)
413 c = (c >> 11) & 0x1f;
414 c = (c * 0xff) / 0x1f;
418 uint8_t G_OF_COLOR(scrntype_t c)
421 c = (c * 0xff) / 0x3f;
425 uint8_t B_OF_COLOR(scrntype_t c)
428 c = (c * 0xff) / 0x1f;
432 uint8_t A_OF_COLOR(scrntype_t c)
439 struct to_upper { // Refer from documentation of libstdc++, GCC5.
440 char operator() (char c) const { return std::toupper(c); }
444 const _TCHAR *get_application_path()
446 static _TCHAR app_path[_MAX_PATH];
447 static bool initialized = false;
450 #if defined(_WIN32) && !defined(_USE_QT)
451 _TCHAR tmp_path[_MAX_PATH], *ptr = NULL;
452 if(GetModuleFileName(NULL, tmp_path, _MAX_PATH) != 0 && GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr) != 0 && ptr != NULL) {
455 my_tcscpy_s(app_path, _MAX_PATH, _T(".\\"));
458 #if defined(Q_OS_WIN)
459 std::string delim = "\\";
461 std::string delim = "/";
463 std::string cpath = cpp_homedir + my_procname + delim;
464 strncpy(app_path, cpath.c_str(), _MAX_PATH);
467 #if !defined(__WIN32) && !defined(__WIN64)
468 if(fstatat(AT_FDCWD, app_path, &st, 0) != 0) {
469 mkdirat(AT_FDCWD, app_path, 0700); // Not found
471 #elif defined(_USE_QT)
472 if(stat(app_path, &st) != 0) {
473 QDir dir = QDir::current();
474 dir.mkdir(QString::fromUtf8(app_path));
477 if(stat(app_path, &st) != 0) {
478 _mkdir(app_path); // Not found
485 return (const _TCHAR *)app_path;
488 const _TCHAR *create_local_path(const _TCHAR *format, ...)
490 static _TCHAR file_path[8][_MAX_PATH];
491 static unsigned int table_index = 0;
492 unsigned int output_index = (table_index++) & 7;
493 _TCHAR file_name[_MAX_PATH];
496 va_start(ap, format);
497 my_vstprintf_s(file_name, _MAX_PATH, format, ap);
499 my_stprintf_s(file_path[output_index], _MAX_PATH, _T("%s%s"), get_application_path(), file_name);
500 return (const _TCHAR *)file_path[output_index];
503 void create_local_path(_TCHAR *file_path, int length, const _TCHAR *format, ...)
505 _TCHAR file_name[_MAX_PATH];
508 va_start(ap, format);
509 my_vstprintf_s(file_name, _MAX_PATH, format, ap);
511 my_stprintf_s(file_path, length, _T("%s%s"), get_application_path(), file_name);
514 const _TCHAR *create_date_file_path(const _TCHAR *extension)
518 get_host_time(&cur_time);
519 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);
522 void create_date_file_path(_TCHAR *file_path, int length, const _TCHAR *extension)
524 my_tcscpy_s(file_path, length, create_date_file_path(extension));
527 bool check_file_extension(const _TCHAR *file_path, const _TCHAR *ext)
530 std::string s_fpath = file_path;
531 std::string s_ext = ext;
534 std::transform(s_fpath.begin(), s_fpath.end(), s_fpath.begin(), to_upper());
535 std::transform(s_ext.begin(), s_ext.end(), s_ext.begin(), to_upper());
536 if(s_fpath.length() < s_ext.length()) return false;
537 pos = s_fpath.rfind(s_ext.c_str(), s_fpath.length());
538 if((pos != std::string::npos) && (pos >= (s_fpath.length() - s_ext.length()))) return true;
541 int nam_len = _tcslen(file_path);
542 int ext_len = _tcslen(ext);
544 return (nam_len >= ext_len && _tcsncicmp(&file_path[nam_len - ext_len], ext, ext_len) == 0);
548 const _TCHAR *get_file_path_without_extensiton(const _TCHAR *file_path)
550 static _TCHAR path[8][_MAX_PATH];
551 static unsigned int table_index = 0;
552 unsigned int output_index = (table_index++) & 7;
554 my_tcscpy_s(path[output_index], _MAX_PATH, file_path);
555 #if defined(_WIN32) && defined(_MSC_VER)
556 PathRemoveExtension(path[output_index]);
558 _TCHAR *p = _tcsrchr(path[output_index], _T('.'));
563 return (const _TCHAR *)path[output_index];
566 void get_long_full_path_name(const _TCHAR* src, _TCHAR* dst, size_t dst_len)
568 _TCHAR tmp[_MAX_PATH];
571 if(GetFullPathName(src, _MAX_PATH, tmp, NULL) == 0) {
572 my_tcscpy_s(dst, dst_len, src);
573 } else if(GetLongPathName(tmp, dst, _MAX_PATH) == 0) {
574 my_tcscpy_s(dst, dst_len, tmp);
577 // write code for your environment
581 const _TCHAR* get_parent_dir(const _TCHAR* file)
583 static _TCHAR path[8][_MAX_PATH];
584 static unsigned int table_index = 0;
585 unsigned int output_index = (table_index++) & 7;
589 GetFullPathName(file, _MAX_PATH, path[output_index], &ptr);
594 // write code for your environment
596 return path[output_index];
599 const _TCHAR *create_string(const _TCHAR* format, ...)
601 static _TCHAR buffer[8][1024];
602 static unsigned int table_index = 0;
603 unsigned int output_index = (table_index++) & 7;
606 va_start(ap, format);
607 my_vstprintf_s(buffer[output_index], 1024, format, ap);
609 return (const _TCHAR *)buffer[output_index];
612 uint32_t get_crc32(uint8_t data[], int size)
614 static bool initialized = false;
615 static uint32_t table[256];
618 for(int i = 0; i < 256; i++) {
620 for(int j = 0; j < 8; j++) {
622 c = (c >> 1) ^ 0xedb88320;
633 for(int i = 0; i < size; i++) {
634 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
639 uint16_t jis_to_sjis(uint16_t jis)
643 tmp.w.l = jis - 0x2121;
644 if(tmp.w.l & 0x100) {
652 tmp.b.h = (tmp.b.h >> 1) + 0x81;
653 if(tmp.w.l >= 0xa000) {
659 int decibel_to_volume(int decibel)
661 // +1 equals +0.5dB (same as fmgen)
662 return (int)(1024.0 * pow(10.0, decibel / 40.0) + 0.5);
665 int32_t apply_volume(int32_t sample, int volume)
679 // if(output > 2147483647) {
680 // return 2147483647;
681 // } else if(output < (-2147483647 - 1)) {
682 // return (-2147483647 - 1);
684 // return (int32_t)output;
689 void get_host_time(cur_time_t* cur_time)
693 GetLocalTime(&sTime);
694 cur_time->year = sTime.wYear;
695 cur_time->month = sTime.wMonth;
696 cur_time->day = sTime.wDay;
697 cur_time->day_of_week = sTime.wDayOfWeek;
698 cur_time->hour = sTime.wHour;
699 cur_time->minute = sTime.wMinute;
700 cur_time->second = sTime.wSecond;
702 time_t timer = time(NULL);
703 struct tm *local = localtime(&timer);
704 cur_time->year = local->tm_year + 1900;
705 cur_time->month = local->tm_mon + 1;
706 cur_time->day = local->tm_mday;
707 cur_time->day_of_week = local->tm_wday;
708 cur_time->hour = local->tm_hour;
709 cur_time->minute = local->tm_min;
710 cur_time->second = local->tm_sec;
714 void cur_time_t::increment()
722 // days in this month
725 days = LEAP_YEAR(year) ? 29 : 28;
726 } else if(month == 4 || month == 6 || month == 9 || month == 11) {
736 if(++day_of_week >= 7) {
744 void cur_time_t::update_year()
749 } else if(year < 100) {
754 void cur_time_t::update_day_of_week()
756 static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
757 int y = year - (month < 3);
758 day_of_week = (y + y / 4 - y / 100 + y / 400 + t[month - 1] + day) % 7;
761 #define STATE_VERSION 1
763 void cur_time_t::save_state(void *f)
765 FILEIO *state_fio = (FILEIO *)f;
767 state_fio->FputUint32(STATE_VERSION);
769 state_fio->FputInt32(year);
770 state_fio->FputInt32(month);
771 state_fio->FputInt32(day);
772 state_fio->FputInt32(day_of_week);
773 state_fio->FputInt32(hour);
774 state_fio->FputInt32(minute);
775 state_fio->FputInt32(second);
776 state_fio->FputBool(initialized);
779 bool cur_time_t::load_state(void *f)
781 FILEIO *state_fio = (FILEIO *)f;
783 if(state_fio->FgetUint32() != STATE_VERSION) {
786 year = state_fio->FgetInt32();
787 month = state_fio->FgetInt32();
788 day = state_fio->FgetInt32();
789 day_of_week = state_fio->FgetInt32();
790 hour = state_fio->FgetInt32();
791 minute = state_fio->FgetInt32();
792 second = state_fio->FgetInt32();
793 initialized = state_fio->FgetBool();