/** * decompressor_gzip_get_file(): Get a file from the archive. * @param zF Open file handle. (Unused in the GZip handler.) * @param filename Filename of the archive. (Unused in the GZip handler.) * @param z_entry Pointer to mdp_z_entry_t element to get from the archive. * @param buf Buffer to read the file into. * @param size Size of buf (in bytes). * @return Number of bytes read, or 0 on error. */ static size_t decompressor_gzip_get_file(FILE *zF, const char *filename, mdp_z_entry_t *z_entry, void *buf, const size_t size) { // Unused parameters. GSFT_UNUSED_PARAMETER(zF); GSFT_UNUSED_PARAMETER(z_entry); // All parameters (except zF and z_entry) must be specified. if (!filename || !buf || !size) return 0; gzFile gzfd; gzfd = gzopen(filename, "rb"); if (!gzfd) { // Error obtaining a GZip file descriptor. return -1; } // Decompress the GZip file into memory. size_t retval = gzread(gzfd, buf, size); gzclose(gzfd); return retval; }
/** * vdpdbg_window_callback_reg_edited(): A register was edited by the user. * @param renderer Cell renderer. * @param path Path in the list store. * @param new_text New text entry. * @param user_data User data. */ static void vdpdbg_window_callback_reg_edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { GSFT_UNUSED_PARAMETER(renderer); GSFT_UNUSED_PARAMETER(user_data); // Convert the text to a number. errno = 0; int new_value = strtol(new_text, NULL, 0); if (errno != 0 || (new_value < 0 || new_value > 0xFF)) return; // Get the register number. GtkTreePath *treePath; GtkTreeIter iter; treePath = gtk_tree_path_new_from_string(path); gtk_tree_model_get_iter(GTK_TREE_MODEL(lmRegList), &iter, treePath); int reg_number; gtk_tree_model_get(GTK_TREE_MODEL(lmRegList), &iter, 0, ®_number, -1); if (reg_number < 0 || reg_number >= 24) { gtk_tree_path_free(treePath); return; } // Set the VDP register. vdpdbg_host_srv->reg_set(&mdp, MDP_REG_IC_VDP, reg_number, new_value); }
/** * mdp_host_reg_set_all(): Set all registers for the specified IC. * @param icID IC ID. * @param reg_struct Pointer to register structure for the specific IC. * @return MDP error code. */ int MDP_FNCALL mdp_host_reg_set_all(mdp_t *plugin, int icID, void *reg_struct) { GSFT_UNUSED_PARAMETER(plugin); if (!Game) return -MDP_ERR_ROM_NOT_LOADED; if (!reg_struct) return -MDP_ERR_INVALID_PARAMETERS; switch (icID) { case MDP_REG_IC_M68K: return mdp_host_reg_set_all_68k(&main68k_context, reg_struct); case MDP_REG_IC_VDP: return mdp_host_reg_set_all_vdp(reg_struct); case MDP_REG_IC_YM2612: return mdp_host_reg_set_all_ym2612(reg_struct); case MDP_REG_IC_PSG: return mdp_host_reg_set_all_psg(reg_struct); case MDP_REG_IC_Z80: return mdp_host_reg_set_all_z80(reg_struct); default: return -MDP_ERR_REG_INVALID_ICID; } }
/** * decompressor_dummy_get_file_info(): Get information from all files in the archive. * @param zF [in] Open file handle. * @param filename [in] Filename of the archive. * @param z_entry_out [out] Pointer to mdp_z_entry_t*, which will contain an allocated mdp_z_entry_t. * @return MDP error code. */ static int decompressor_dummy_get_file_info(FILE *zF, const char* filename, mdp_z_entry_t** z_entry_out) { GSFT_UNUSED_PARAMETER(filename); if (!zF || !z_entry_out) return -MDP_ERR_INVALID_PARAMETERS; // The dummy decompressor treats the file as a single, uncompressed file. // Seek to the end of the file and get the position. fseek(zF, 0, SEEK_END); size_t filesize = ftell(zF); // Allocate memory for the mdp_z_entry_t. mdp_z_entry_t *z_entry = (mdp_z_entry_t*)malloc(sizeof(mdp_z_entry_t)); // Set the elements of the list. z_entry->filesize = filesize; z_entry->filename = (filename ? strdup(filename) : NULL); z_entry->next = NULL; // Return the list. *z_entry_out = z_entry; return MDP_ERR_OK; }
/** * decompressor_dummy_detect_format(): Detect if this file can be handled by this decompressor. * @param zF Open file handle. * @return Non-zero if this file can be handled; 0 if it can't be. */ static int decompressor_dummy_detect_format(FILE *zF) { GSFT_UNUSED_PARAMETER(zF); // The dummy decompressor accepts all files. return 1; }
/** * decompressor_dummy_get_file(): Get a file from the archive. * @param zF [in] Open file handle. * @param filename [in] Filename of the archive. * @param file_list [in] Pointer to decompressor_file_list_t element to get from the archive. * @param buf [in] Buffer to read the file into. * @param size [in] Size of buf (in bytes). * @param ret_size [in] Pointer to size_t to store the number of bytes read. * @return MDP error code. */ static int decompressor_dummy_get_file(FILE *zF, const char *filename, mdp_z_entry_t *z_entry, void *buf, const size_t size, size_t *ret_size) { GSFT_UNUSED_PARAMETER(filename); GSFT_UNUSED_PARAMETER(z_entry); // All parameters (except filename and file_list) must be specified. if (!zF || !buf || !size || !ret_size) return -MDP_ERR_INVALID_PARAMETERS; // Seek to the beginning of the file. fseek(zF, 0, SEEK_SET); // Read the file into the buffer. *ret_size = fread(buf, 1, size, zF); return MDP_ERR_OK; }
/** * audio_sdl_callback(): SDL audio callback. * @param user * @param buffer * @param len */ static void audio_sdl_callback(void *user, uint8_t *buffer, int len) { GSFT_UNUSED_PARAMETER(user); if (audio_sdl_len < len) { memcpy(buffer, audio_sdl_audiobuf, audio_sdl_len); audio_sdl_len = 0; return; } memcpy(buffer, audio_sdl_audiobuf, len); audio_sdl_len -= len; memmove(audio_sdl_audiobuf, audio_sdl_audiobuf + len, audio_sdl_len); }
/** * SendMessageUW_LPCSTR(): Convert LPARAM from UTF-8 to UTF-16, then call SendMessageW(). * @param hWnd hWnd. * @param msgA ANSI message. * @param msgW Unicode message. * @param wParam wParam. * @param lParam lParam. (LPCSTR) * @return Result. */ static WINUSERAPI LRESULT WINAPI SendMessageUW_LPCSTR(HWND hWnd, UINT msgA, UINT msgW, WPARAM wParam, LPARAM lParam) { GSFT_UNUSED_PARAMETER(msgA); if (!lParam) return SendMessageW(hWnd, msgW, wParam, lParam); // Convert lParam from UTF-8 to UTF-16. wchar_t *lwParam = w32u_UTF8toUTF16((char*)lParam); // Send the message. LRESULT lRet = SendMessageW(hWnd, msgW, wParam, (LPARAM)lwParam); free(lwParam); return lRet; }
/** * decompressor_gzip_get_file_info(): Get information about all files in the archive. * @param zF [in] Open file handle. * @param filename [in] Filename of the archive. * @param z_entry_out [out] Pointer to mdp_z_entry_t*, which will contain an allocated mdp_z_entry_t. * @return MDP error code. */ static int decompressor_gzip_get_file_info(FILE *zF, const char* filename, mdp_z_entry_t** z_entry_out) { GSFT_UNUSED_PARAMETER(zF); // GZip-compressed files can only have one file. gzFile gzfd; unsigned char buf[1024]; gzfd = gzopen(filename, "rb"); if (!gzfd) { // Error obtaining a GZip file descriptor. return -MDP_ERR_Z_CANT_OPEN_ARCHIVE; } // Read through the GZip file until we hit an EOF. int filesize = 0; while (!gzeof(gzfd)) { filesize += gzread(gzfd, buf, 1024); } // Close the GZip fd. gzclose(gzfd); // Allocate memory for the mdp_z_entry_t. mdp_z_entry_t *z_entry = (mdp_z_entry_t*)malloc(sizeof(mdp_z_entry_t)); // Set the elements of the list. z_entry->filename = (filename ? strdup(filename) : NULL); z_entry->filesize = filesize; z_entry->next = NULL; // Return the list. *z_entry_out = z_entry; return MDP_ERR_OK; }
/** * decompressor_rar_win32_get_file_info(): Get information about all files in the archive. * @param zF [in] Open file handle. * @param filename [in] Filename of the archive. * @param z_entry_out [out] Pointer to mdp_z_entry_t*, which will contain an allocated mdp_z_entry_t. * @return MDP error code. */ int decompressor_rar_win32_get_file_info(FILE *zF, const char* filename, mdp_z_entry_t** z_entry_out) { GSFT_UNUSED_PARAMETER(zF); // Initialize UnRAR.dll. UnRAR_dll dll; if (!dll.load(Misc_Filenames.RAR_Binary, PathNames.Gens_EXE_Path)) { // Error initializing UnRAR.dll from the EXE path. // Try the save path. if (!dll.load(Misc_Filenames.RAR_Binary, PathNames.Gens_Save_Path)) { // Error initializing UnRAR.dll from the save path. // TODO: Determine if it was a missing DLL or a missing symbol. return -MDP_ERR_Z_EXE_NOT_FOUND; } } HANDLE hRar; char *filenameA = NULL; wchar_t *filenameW = NULL; // Open the RAR file. struct RAROpenArchiveDataEx rar_open; rar_open.OpenMode = RAR_OM_LIST; rar_open.CmtBuf = NULL; rar_open.CmtBufSize = 0; if (w32u_is_unicode) { // Unicode mode. filenameW = w32u_UTF8toUTF16(filename); rar_open.ArcName = NULL; rar_open.ArcNameW = filenameW; } else { // ANSI mode. // TODO: Do we need to convert from ANSI to UTF-8? filenameA = strdup(filename); rar_open.ArcName = filenameA; rar_open.ArcNameW = NULL; } hRar = dll.pRAROpenArchiveEx(&rar_open); if (!hRar) { // Error opening the RAR file. free(filenameW); return -MDP_ERR_Z_CANT_OPEN_ARCHIVE; } // File list pointers. mdp_z_entry_t *z_entry_head = NULL; mdp_z_entry_t *z_entry_end = NULL; // Process the archive. struct RARHeaderDataEx rar_header; char utf8_buf[1024*4]; int ret; while ((ret = dll.pRARReadHeaderEx(hRar, &rar_header)) == 0) { // Allocate memory for the file. mdp_z_entry_t *z_entry_cur = (mdp_z_entry_t*)malloc(sizeof(*z_entry_cur)); // Store the ROM file information. // TODO: What do we do if rar_header.UnpSizeHigh is set (indicating >4 GB)? z_entry_cur->filesize = rar_header.UnpSize; z_entry_cur->next = NULL; // Check which filename should be used. if (w32u_is_unicode) { // Use the Unicode filename. (rar_header.FileNameW) WideCharToMultiByte(CP_UTF8, 0, rar_header.FileNameW, -1, utf8_buf, sizeof(utf8_buf), NULL, NULL); z_entry_cur->filename = strdup(utf8_buf); } else { // Use the ANSI filename. (rar_header.FileName) // TODO: Do we need to convert from ANSI to UTF-8? z_entry_cur->filename = strdup(rar_header.FileName); } if (!z_entry_head) { // List hasn't been created yet. Create it. z_entry_head = z_entry_cur; z_entry_end = z_entry_cur; } else { // Append the file list entry to the end of the list. z_entry_end->next = z_entry_cur; z_entry_end = z_entry_cur; } // Go to the next file. if (dll.pRARProcessFile(hRar, RAR_SKIP, NULL, NULL) != 0) break; } // Close the RAR file. dll.pRARCloseArchive(hRar); free(filenameA); free(filenameW); // Return the list of files. *z_entry_out = z_entry_head; return MDP_ERR_OK; }
/** * decompressor_rar_win32_get_file(): Get a file from the archive. * @param zF [in] Open file handle. * @param filename [in] Filename of the archive. * @param file_list [in] Pointer to decompressor_file_list_t element to get from the archive. * @param buf [in] Buffer to read the file into. * @param size [in] Size of buf (in bytes). * @param ret_size [in] Pointer to size_t to store the number of bytes read. * @return MDP error code. */ int decompressor_rar_win32_get_file(FILE *zF, const char *filename, mdp_z_entry_t *z_entry, void *buf, const size_t size, size_t *ret_size) { GSFT_UNUSED_PARAMETER(zF); // Initialize UnRAR.dll. UnRAR_dll dll; if (!dll.load(Misc_Filenames.RAR_Binary, PathNames.Gens_EXE_Path)) { // Error initializing UnRAR.dll from the EXE path. // Try the save path. if (!dll.load(Misc_Filenames.RAR_Binary, PathNames.Gens_Save_Path)) { // Error initializing UnRAR.dll from the save path. // TODO: Determine if it was a missing DLL or a missing symbol. return -MDP_ERR_Z_EXE_NOT_FOUND; } } HANDLE hRar; char *filenameA = NULL; wchar_t *filenameW = NULL; // Open the RAR file. struct RAROpenArchiveDataEx rar_open; rar_open.OpenMode = RAR_OM_EXTRACT; rar_open.CmtBuf = NULL; rar_open.CmtBufSize = 0; if (w32u_is_unicode) { // Unicode mode. filenameW = w32u_UTF8toUTF16(filename); rar_open.ArcName = NULL; rar_open.ArcNameW = filenameW; } else { // ANSI mode. // TODO: Do we need to convert from ANSI to UTF-8? filenameA = strdup(filename); rar_open.ArcName = filenameA; rar_open.ArcNameW = NULL; } hRar = dll.pRAROpenArchiveEx(&rar_open); if (!hRar) { // Error opening the RAR file. free(filenameW); return -MDP_ERR_Z_CANT_OPEN_ARCHIVE; } // If we're using Unicode, convert the selected filename to Unicode. wchar_t *z_filenameW = NULL; if (w32u_is_unicode) z_filenameW = w32u_UTF8toUTF16(z_entry->filename); // Search for the file. struct RARHeaderDataEx rar_header; *ret_size = 0; int ret, cmp; while ((ret = dll.pRARReadHeaderEx(hRar, &rar_header)) == 0) { if (w32u_is_unicode) { // Unicode mode. cmp = p_wcsicmp(z_filenameW, rar_header.FileNameW); } else { // ANSI mode. // TODO: Do we need to convert from ANSI to UTF-8? cmp = _stricmp(z_entry->filename, rar_header.FileName); } if (cmp != 0) { // Not a match. Skip the file. if (dll.pRARProcessFile(hRar, RAR_SKIP, NULL, NULL) != 0) break; continue; } // Found the file. // Create the RAR state. RarState_t rar_state; rar_state.buf = (uint8_t*)buf; rar_state.size = size; rar_state.pos = 0; // Set up the RAR callback. dll.pRARSetCallback(hRar, &decompressor_rar_win32_callback, (LPARAM)&rar_state); // Process the file. // Possible errors: // - 0: Success. // - ERAR_UNKNOWN: Read the maximum amount of data for the ubuffer. // - Others: Read error; abort. (TODO: Show an error message.) ret = dll.pRARProcessFile(hRar, RAR_TEST, NULL, NULL); // TODO: md_rar.cpp returns the filesize processed on error. // This just returns 0. if (ret != 0 && ret != ERAR_UNKNOWN) break; // File processed. *ret_size = rar_state.pos; break; } // Close the RAR file. dll.pRARCloseArchive(hRar); free(filenameA); free(filenameW); free(z_filenameW); return MDP_ERR_OK; }