From 99241183a54ac264461447e93cef3a5c0432ac21 Mon Sep 17 00:00:00 2001 From: gbeauche <> Date: Tue, 28 Mar 2006 07:01:19 +0000 Subject: [PATCH] Fix pollmedia on Windows, it's no longer necessary to boot with a CD-ROM in the drive to use it. Side effect: media can be changed without problems now --- BasiliskII/src/SDL/video_sdl.cpp | 51 +++++++++++ BasiliskII/src/Windows/sys_windows.cpp | 114 +++++++++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/BasiliskII/src/SDL/video_sdl.cpp b/BasiliskII/src/SDL/video_sdl.cpp index c415be5d..d15618dd 100644 --- a/BasiliskII/src/SDL/video_sdl.cpp +++ b/BasiliskII/src/SDL/video_sdl.cpp @@ -203,6 +203,44 @@ static inline void vm_release_framebuffer(void *fb, uint32 size) } +/* + * Windows message handler + */ + +#ifdef WIN32 +#include +static WNDPROC sdl_window_proc = NULL; // Window proc used by SDL + +extern void SysMediaArrived(void); +extern void SysMediaRemoved(void); +extern HWND GetMainWindowHandle(void); + +static LRESULT CALLBACK windows_message_handler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_DEVICECHANGE: + if (wParam == DBT_DEVICEREMOVECOMPLETE) { + DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; + if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) + SysMediaRemoved(); + } + else if (wParam == DBT_DEVICEARRIVAL) { + DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam; + if (p->dbch_devicetype == DBT_DEVTYP_VOLUME) + SysMediaArrived(); + } + return 0; + + default: + if (sdl_window_proc) + return CallWindowProc(sdl_window_proc, hwnd, msg, wParam, lParam); + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} +#endif + + /* * SheepShaver glue */ @@ -1025,6 +1063,13 @@ bool SDL_monitor_desc::video_open(void) return false; } +#ifdef WIN32 + // Chain in a new message handler for WM_DEVICECHANGE + HWND the_window = GetMainWindowHandle(); + sdl_window_proc = (WNDPROC)GetWindowLongPtr(the_window, GWLP_WNDPROC); + SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)windows_message_handler); +#endif + // Initialize VideoRefresh function VideoRefreshInit(); @@ -1259,6 +1304,12 @@ void SDL_monitor_desc::video_close(void) { D(bug("video_close()\n")); +#ifdef WIN32 + // Remove message handler for WM_DEVICECHANGE + HWND the_window = GetMainWindowHandle(); + SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)sdl_window_proc); +#endif + // Stop redraw thread #ifndef USE_CPU_EMUL_SERVICES if (redraw_thread_active) { diff --git a/BasiliskII/src/Windows/sys_windows.cpp b/BasiliskII/src/Windows/sys_windows.cpp index 51e7870d..0c866e49 100755 --- a/BasiliskII/src/Windows/sys_windows.cpp +++ b/BasiliskII/src/Windows/sys_windows.cpp @@ -45,6 +45,14 @@ using std::min; #include "debug.h" +// Supported media types +enum { + MEDIA_FLOPPY = 1, + MEDIA_CD = 2, + MEDIA_HD = 4, + MEDIA_REMOVABLE = MEDIA_FLOPPY | MEDIA_CD +}; + // File handles are pointers to these structures struct file_handle { char *name; // Copy of device/file name @@ -59,6 +67,13 @@ struct file_handle { bool is_media_present; }; +// Open file handles +struct open_file_handle { + file_handle *fh; + open_file_handle *next; +}; +static open_file_handle *open_file_handles = NULL; + // File handle of first floppy drive (for SysMountFirstFloppy()) static file_handle *first_floppy = NULL; @@ -66,6 +81,9 @@ static file_handle *first_floppy = NULL; static const int CD_READ_AHEAD_SECTORS = 16; static char *sector_buffer = NULL; +// Prototypes +static bool is_cdrom_readable(file_handle *fh); + /* * Initialization @@ -92,6 +110,94 @@ void SysExit(void) } +/* + * Manage open file handles + */ + +static void sys_add_file_handle(file_handle *fh) +{ + open_file_handle *p = new open_file_handle; + p->fh = fh; + p->next = open_file_handles; + open_file_handles = p; +} + +static void sys_remove_file_handle(file_handle *fh) +{ + open_file_handle *p = open_file_handles; + open_file_handle *q = NULL; + + while (p) { + if (p->fh == fh) { + if (q) + q->next = p->next; + else + open_file_handles = p->next; + delete p; + break; + } + q = p; + p = p->next; + } +} + + +/* + * Mount removable media now + */ + +void mount_removable_media(int media) +{ + for (open_file_handle *p = open_file_handles; p != NULL; p = p->next) { + file_handle * const fh = p->fh; + + if (fh->is_cdrom && (media & MEDIA_CD)) { + cache_clear(&fh->cache); + fh->start_byte = 0; + + if (fh->fh && fh->fh != INVALID_HANDLE_VALUE) + CloseHandle(fh->fh); + + // Re-open device + char device_name[MAX_PATH]; + sprintf(device_name, "\\\\.\\%c:", fh->name[0]); + fh->fh = CreateFile( + device_name, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (fh->fh != INVALID_HANDLE_VALUE) { + fh->is_media_present = is_cdrom_readable(fh); + if (fh->is_media_present) + MountVolume(fh); + } else { + fh->is_media_present = false; + } + } + } +} + + +/* + * Account for media that has just arrived + */ + +void SysMediaArrived(void) +{ + mount_removable_media(MEDIA_REMOVABLE); +} + + +/* + * Account for media that has just been removed + */ + +void SysMediaRemoved(void) +{ +} + + /* * Mount first floppy disk */ @@ -350,6 +456,9 @@ void *Sys_open(const char *path_name, bool read_only) fh->start_byte = 0; fh->is_floppy = false; fh->is_cdrom = true; + memset(&fh->cache, 0, sizeof(cachetype)); + cache_init(&fh->cache); + cache_clear(&fh->cache); if (!PrefsFindBool("nocdrom")) fh->is_media_present = is_cdrom_readable(fh); } @@ -399,6 +508,9 @@ void *Sys_open(const char *path_name, bool read_only) if (fh->is_floppy && first_floppy == NULL) first_floppy = fh; + if (fh) + sys_add_file_handle(fh); + return fh; } @@ -413,6 +525,8 @@ void Sys_close(void *arg) if (!fh) return; + sys_remove_file_handle(fh); + if (fh->is_cdrom) { cache_final(&fh->cache); SysAllowRemoval((void *)fh);