2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 #if !defined(__WIN32) && !defined(__WIN64)
19 #include <sys/types.h>
22 #include "agar_logger.h"
30 #pragma comment(lib, "shlwapi.lib")
39 uint32 EndianToLittle_DWORD(uint32 x)
41 #if defined(__LITTLE_ENDIAN__)
45 y = ((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) |
46 ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24);
51 uint16 EndianToLittle_WORD(uint16 x)
53 #if defined(__LITTLE_ENDIAN__)
57 y = ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
72 unsigned int max(unsigned int a, unsigned int b)
90 unsigned int min(unsigned int a, unsigned int b)
101 #ifndef SUPPORT_SECURE_FUNCTIONS
102 errno_t my_strcpy_s(char *strDestination, size_t numberOfElements, const char *strSource)
104 strcpy(strDestination, strSource);
108 errno_t my_tcscpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource)
110 _tcscpy(strDestination, strSource);
114 errno_t my_strncpy_s(char *strDestination, size_t numberOfElements, const char *strSource, size_t count)
116 strncpy(strDestination, strSource, count);
120 errno_t my_tcsncpy_s(_TCHAR *strDestination, size_t numberOfElements, const _TCHAR *strSource, size_t count)
122 _tcsncpy(strDestination, strSource, count);
126 char *my_strtok_s(char *strToken, const char *strDelimit, char **context)
128 return strtok(strToken, strDelimit);
131 _TCHAR *my_tcstok_s(_TCHAR *strToken, const char *strDelimit, _TCHAR **context)
133 return _tcstok(strToken, strDelimit);
136 int my_sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
139 va_start(ap, format);
140 int result = vsprintf(buffer, format, ap);
145 int my_stprintf_s(_TCHAR *buffer, size_t sizeOfBuffer, const _TCHAR *format, ...)
148 va_start(ap, format);
149 int result = _vstprintf(buffer, format, ap);
154 int my_vsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr)
156 return vsprintf(buffer, format, argptr);
159 int my_vstprintf_s(_TCHAR *buffer, size_t numberOfElements, const _TCHAR *format, va_list argptr)
161 return _vstprintf(buffer, format, argptr);
167 BOOL MyWritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName)
170 FILEIO* fio_i = new FILEIO();
171 if(fio_i->Fopen(lpFileName, FILEIO_READ_ASCII)) {
172 char tmp_path[_MAX_PATH];
173 my_sprintf_s(tmp_path, _MAX_PATH, "%s.$$$", lpFileName);
174 FILEIO* fio_o = new FILEIO();
175 if(fio_o->Fopen(tmp_path, FILEIO_WRITE_ASCII)) {
176 bool in_section = false;
177 char section[1024], line[1024], *equal;
178 my_sprintf_s(section, 1024, "[%s]", lpAppName);
179 while(fio_i->Fgets(line, 1024) != NULL && strlen(line) > 0) {
180 if(line[strlen(line) - 1] == '\n') {
181 line[strlen(line) - 1] = '\0';
186 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
188 } else if(strcmp(line, section) == 0) {
191 } else if(in_section && (equal = strstr(line, "=")) != NULL) {
193 if(strcmp(line, lpKeyName) == 0) {
194 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
201 fio_o->Fprintf("%s\n", line);
205 fio_o->Fprintf("[%s]\n", lpAppName);
207 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
215 if(!(FILEIO::RemoveFile(lpFileName) && FILEIO::RenameFile(tmp_path, lpFileName))) {
220 FILEIO* fio_o = new FILEIO();
221 if(fio_o->Fopen(lpFileName, FILEIO_WRITE_ASCII)) {
222 fio_o->Fprintf("[%s]\n", lpAppName);
223 fio_o->Fprintf("%s=%s\n", lpKeyName, lpString);
232 static std::string MyGetPrivateProfileStr(const _TCHAR *lpAppName, const _TCHAR *lpKeyName, _TCHAR *lpFileName)
235 char ibuf[4096 + 102];
239 std::string::size_type pos;
242 FILEIO *pf = new FILEIO;
246 key = key + lpKeyName;
248 if(pf->Fopen(lpFileName, FILEIO_READ_ASCII) != true) {
252 AGAR_DebugLog(AGAR_LOG_DEBUG, "Try App: %s Key: %s", lpAppName, lpKeyName);
253 pf->Fseek(0, FILEIO_SEEK_SET);
260 if(l_len > (4096 + 100)) { // Too long, read dummy.
261 c = (char)pf->Fgetc();
262 if((c != EOF) && (c != '\n') && (c != '\0')) continue;
265 c = (char)pf->Fgetc();
266 if((c == EOF) || (c == '\n') || (c == '\0')) break;
274 key_str = key_str + "=";
275 pos = got_str.find(key_str);
276 if(pos != std::string::npos) break;
277 if(c == EOF) return "";
282 got_str.erase(0, pos + key_str.length());
283 AGAR_DebugLog(AGAR_LOG_DEBUG, "Got: %s Length: %d", got_str.c_str(), got_str.length());
288 DWORD MyGetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPCTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName)
290 if(lpDefault != NULL) {
291 my_strcpy_s(lpReturnedString, nSize, lpDefault);
293 lpReturnedString[0] = '\0';
295 FILEIO* fio = new FILEIO();
296 if(fio->Fopen(lpFileName, FILEIO_READ_ASCII)) {
297 bool in_section = false;
298 char section[1024], line[1024], *equal;
299 my_sprintf_s(section, 1024, "[%s]", lpAppName);
300 while(fio->Fgets(line, 1024) != NULL && strlen(line) > 0) {
301 if(line[strlen(line) - 1] == '\n') {
302 line[strlen(line) - 1] = '\0';
307 } else if(strcmp(line, section) == 0) {
310 } else if(in_section && (equal = strstr(line, "=")) != NULL) {
312 if(strcmp(line, lpKeyName) == 0) {
313 my_strcpy_s(lpReturnedString, nSize, equal + 1);
321 return strlen(lpReturnedString);
324 UINT MyGetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName)
326 // write your compatible function, if possible in standard C/C++ code
331 memset(sstr, 0x00, sizeof(sstr));
332 memset(sval, 0x00, sizeof(sval));
333 snprintf(sval, 128, "%d", nDefault);
334 MyGetPrivateProfileString(lpAppName,lpKeyName, sval, sstr, 128, lpFileName);
340 i = strtol(s.c_str(), NULL, 10);
342 //AGAR_DebugLog(AGAR_LOG_DEBUG, "Got Int: %d\n", i);
348 scrntype RGB_COLOR(uint r, uint g, uint b)
350 scrntype rr = ((scrntype)r * 0x1f) / 0xff;
351 scrntype gg = ((scrntype)g * 0x1f) / 0xff;
352 scrntype bb = ((scrntype)b * 0x1f) / 0xff;
353 return (rr << 10) | (gg << 5) | bb;
356 scrntype RGBA_COLOR(uint r, uint g, uint b, uint a)
358 return RGB_COLOR(r, g, b);
361 uint8 R_OF_COLOR(scrntype c)
363 c = (c >> 10) & 0x1f;
364 c = (c * 0xff) / 0x1f;
368 uint8 G_OF_COLOR(scrntype c)
371 c = (c * 0xff) / 0x1f;
375 uint8 B_OF_COLOR(scrntype c)
378 c = (c * 0xff) / 0x1f;
382 uint8 A_OF_COLOR(scrntype c)
386 #elif defined(_RGB565)
387 scrntype RGB_COLOR(uint r, uint g, uint b)
389 scrntype rr = ((scrntype)r * 0x1f) / 0xff;
390 scrntype gg = ((scrntype)g * 0x3f) / 0xff;
391 scrntype bb = ((scrntype)b * 0x1f) / 0xff;
392 return (rr << 11) | (gg << 5) | bb;
395 scrntype RGBA_COLOR(uint r, uint g, uint b, uint a)
397 return RGB_COLOR(r, g, b);
400 uint8 R_OF_COLOR(scrntype c)
402 c = (c >> 11) & 0x1f;
403 c = (c * 0xff) / 0x1f;
407 uint8 G_OF_COLOR(scrntype c)
410 c = (c * 0xff) / 0x3f;
414 uint8 B_OF_COLOR(scrntype c)
417 c = (c * 0xff) / 0x1f;
421 uint8 A_OF_COLOR(scrntype c)
429 struct to_upper { // Refer from documentation of libstdc++, GCC5.
430 char operator() (char c) const { return std::toupper(c); }
434 extern std::string cpp_homedir;
435 extern std::string my_procname;
438 const _TCHAR *get_application_path()
440 static _TCHAR app_path[_MAX_PATH];
441 static bool initialized = false;
445 _TCHAR tmp_path[_MAX_PATH], *ptr = NULL;
446 if(GetModuleFileName(NULL, tmp_path, _MAX_PATH) != 0 && GetFullPathName(tmp_path, _MAX_PATH, app_path, &ptr) != 0 && ptr != NULL) {
449 my_tcscpy_s(app_path, _MAX_PATH, _T(".\\"));
452 #if defined(Q_OS_WIN)
453 std::string delim = "\\";
455 std::string delim = "/";
457 std::string cpath = cpp_homedir + my_procname + delim;
458 strncpy(app_path, cpath.c_str(), _MAX_PATH);
461 #if !defined(__WIN32) && !defined(__WIN64)
462 if(fstatat(AT_FDCWD, app_path, &st, 0) != 0) {
463 mkdirat(AT_FDCWD, app_path, 0700); // Not found
466 # if defined(Q_OS_WIN)
467 if(stat(app_path, &st) != 0) {
468 mkdir(app_path); // Not found
471 if(stat(app_path, &st) != 0) {
472 _mkdir(app_path); // Not found
481 return (const _TCHAR *)app_path;
484 const _TCHAR *create_local_path(const _TCHAR *format, ...)
486 static _TCHAR file_path[8][_MAX_PATH];
487 static unsigned int table_index = 0;
488 unsigned int output_index = (table_index++) & 7;
489 _TCHAR file_name[_MAX_PATH];
492 va_start(ap, format);
493 my_vstprintf_s(file_name, _MAX_PATH, format, ap);
495 my_stprintf_s(file_path[output_index], _MAX_PATH, _T("%s%s"), get_application_path(), file_name);
496 return (const _TCHAR *)file_path[output_index];
499 void create_local_path(_TCHAR *file_path, int length, const _TCHAR *format, ...)
501 _TCHAR file_name[_MAX_PATH];
504 va_start(ap, format);
505 my_vstprintf_s(file_name, _MAX_PATH, format, ap);
507 my_stprintf_s(file_path, length, _T("%s%s"), get_application_path(), file_name);
510 const _TCHAR *create_date_file_path(const _TCHAR *extension)
514 get_host_time(&cur_time);
515 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);
518 void create_date_file_path(_TCHAR *file_path, int length, const _TCHAR *extension)
520 my_tcscpy_s(file_path, length, create_date_file_path(extension));
523 bool check_file_extension(const _TCHAR *file_path, const _TCHAR *ext)
526 std::string s_fpath = file_path;
527 std::string s_ext = ext;
530 std::transform(s_fpath.begin(), s_fpath.end(), s_fpath.begin(), to_upper());
531 std::transform(s_ext.begin(), s_ext.end(), s_ext.begin(), to_upper());
532 if(s_fpath.length() < s_ext.length()) return false;
533 pos = s_fpath.rfind(s_ext.c_str(), s_fpath.length());
534 if((pos != std::string::npos) && (pos >= (s_fpath.length() - s_ext.length()))) return true;
537 int nam_len = _tcslen(file_path);
538 int ext_len = _tcslen(ext);
540 return (nam_len >= ext_len && _tcsncicmp(&file_path[nam_len - ext_len], ext, ext_len) == 0);
544 const _TCHAR *get_file_path_without_extensiton(const _TCHAR *file_path)
546 static _TCHAR path[8][_MAX_PATH];
547 static unsigned int table_index = 0;
548 unsigned int output_index = (table_index++) & 7;
550 my_tcscpy_s(path[output_index], _MAX_PATH, file_path);
552 PathRemoveExtension(path[output_index]);
554 _TCHAR *p = _tcsrchr(path[output_index], _T('.'));
559 return (const _TCHAR *)path[output_index];
562 const _TCHAR *create_string(const _TCHAR* format, ...)
564 static _TCHAR buffer[8][1024];
565 static unsigned int table_index = 0;
566 unsigned int output_index = (table_index++) & 7;
569 va_start(ap, format);
570 my_vstprintf_s(buffer[output_index], 1024, format, ap);
572 return (const _TCHAR *)buffer[output_index];
575 uint32 get_crc32(uint8 data[], int size)
577 static bool initialized = false;
578 static uint32 table[256];
581 for(int i = 0; i < 256; i++) {
583 for(int j = 0; j < 8; j++) {
585 c = (c >> 1) ^ 0xedb88320;
596 for(int i = 0; i < size; i++) {
597 c = table[(c ^ data[i]) & 0xff] ^ (c >> 8);
602 uint16 jis_to_sjis(uint16 jis)
606 tmp.w.l = jis - 0x2121;
607 if(tmp.w.l & 0x100) {
615 tmp.b.h = (tmp.b.h >> 1) + 0x81;
616 if(tmp.w.l >= 0xa000) {
622 int decibel_to_volume(int decibel)
624 // +1 equals +0.5dB (same as fmgen)
625 return (int)(1024.0 * pow(10.0, decibel / 40.0) + 0.5);
628 int32 apply_volume(int32 sample, int volume)
642 // if(output > 2147483647) {
643 // return 2147483647;
644 // } else if(output < (-2147483647 - 1)) {
645 // return (-2147483647 - 1);
647 // return (int32)output;
652 void get_host_time(cur_time_t* cur_time)
656 GetLocalTime(&sTime);
657 cur_time->year = sTime.wYear;
658 cur_time->month = sTime.wMonth;
659 cur_time->day = sTime.wDay;
660 cur_time->day_of_week = sTime.wDayOfWeek;
661 cur_time->hour = sTime.wHour;
662 cur_time->minute = sTime.wMinute;
663 cur_time->second = sTime.wSecond;
665 time_t timer = time(NULL);
666 struct tm *local = localtime(&timer);
667 cur_time->year = local->tm_year + 1900;
668 cur_time->month = local->tm_mon + 1;
669 cur_time->day = local->tm_mday;
670 cur_time->day_of_week = local->tm_wday;
671 cur_time->hour = local->tm_hour;
672 cur_time->minute = local->tm_min;
673 cur_time->second = local->tm_sec;
677 void cur_time_t::increment()
685 // days in this month
688 days = LEAP_YEAR(year) ? 29 : 28;
689 } else if(month == 4 || month == 6 || month == 9 || month == 11) {
699 if(++day_of_week >= 7) {
707 void cur_time_t::update_year()
712 } else if(year < 100) {
717 void cur_time_t::update_day_of_week()
719 static const int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
720 int y = year - (month < 3);
721 day_of_week = (y + y / 4 - y / 100 + y / 400 + t[month - 1] + day) % 7;
724 #define STATE_VERSION 1
726 void cur_time_t::save_state(void *f)
728 FILEIO *state_fio = (FILEIO *)f;
730 state_fio->FputUint32(STATE_VERSION);
732 state_fio->FputInt32(year);
733 state_fio->FputInt32(month);
734 state_fio->FputInt32(day);
735 state_fio->FputInt32(day_of_week);
736 state_fio->FputInt32(hour);
737 state_fio->FputInt32(minute);
738 state_fio->FputInt32(second);
739 state_fio->FputBool(initialized);
742 bool cur_time_t::load_state(void *f)
744 FILEIO *state_fio = (FILEIO *)f;
746 if(state_fio->FgetUint32() != STATE_VERSION) {
749 year = state_fio->FgetInt32();
750 month = state_fio->FgetInt32();
751 day = state_fio->FgetInt32();
752 day_of_week = state_fio->FgetInt32();
753 hour = state_fio->FgetInt32();
754 minute = state_fio->FgetInt32();
755 second = state_fio->FgetInt32();
756 initialized = state_fio->FgetBool();