static HRESULT create_surface(dd_info *dd, DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type) { HRESULT result; // create the surface as requested result = IDirectDraw7_CreateSurface(dd->ddraw, desc, surface, NULL); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X creating %s surface\n"), (int)result, type); return result; } // get a description of the primary surface result = IDirectDrawSurface7_GetSurfaceDesc(*surface, desc); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X getting %s surface desciption\n"), (int)result, type); IDirectDrawSurface7_Release(*surface); *surface = NULL; return result; } // print out the good stuff osd_printf_verbose(_WINDOWS("DirectDraw: %s surface created: %dx%dx%d (R=%08X G=%08X B=%08X)\n"), type, (int)desc->dwWidth, (int)desc->dwHeight, (int)desc->ddpfPixelFormat.dwRGBBitCount, (UINT32)desc->ddpfPixelFormat.dwRBitMask, (UINT32)desc->ddpfPixelFormat.dwGBitMask, (UINT32)desc->ddpfPixelFormat.dwBBitMask); return result; }
static int create_clipper(win_window_info *window) { dd_info *dd = (dd_info *)window->drawdata; HRESULT result; // create a clipper for the primary surface result = IDirectDraw7_CreateClipper(dd->ddraw, 0, &dd->clipper, NULL); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X creating clipper\n"), (int)result); return 1; } // set the clipper's hwnd result = IDirectDrawClipper_SetHWnd(dd->clipper, 0, window->hwnd); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X setting clipper hwnd\n"), (int)result); return 1; } // set the clipper on the primary surface result = IDirectDrawSurface7_SetClipper(dd->primary, dd->clipper); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X setting clipper on primary surface\n"), (int)result); return 1; } return 0; }
static void pick_best_mode(win_window_info *window) { dd_info *dd = (dd_info *)window->drawdata; mode_enum_info einfo; HRESULT result; // determine the minimum width/height for the selected target // note: technically we should not be calling this from an alternate window // thread; however, it is only done during init time, and the init code on // the main thread is waiting for us to finish, so it is safe to do so here window->target->compute_minimum_size(einfo.minimum_width, einfo.minimum_height); // use those as the target for now einfo.target_width = einfo.minimum_width * MAX(1, video_config.prescale); einfo.target_height = einfo.minimum_height * MAX(1, video_config.prescale); // determine the refresh rate of the primary screen einfo.target_refresh = 60.0; const screen_device *primary_screen = window->machine().config().first_screen(); if (primary_screen != NULL) einfo.target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); printf("Target refresh = %f\n", einfo.target_refresh); // if we're not stretching, allow some slop on the minimum since we can handle it if (!video_config.hwstretch) { einfo.minimum_width -= 4; einfo.minimum_height -= 4; } // if we are stretching, aim for a mode approximately 2x the game's resolution else if (video_config.prescale <= 1) { einfo.target_width *= 2; einfo.target_height *= 2; } // fill in the rest of the data einfo.window = window; einfo.best_score = 0.0f; // enumerate the modes osd_printf_verbose(_WINDOWS("DirectDraw: Selecting video mode...\n")); result = IDirectDraw7_EnumDisplayModes(dd->ddraw, DDEDM_REFRESHRATES, NULL, &einfo, enum_modes_callback); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during EnumDisplayModes call\n"), (int)result); osd_printf_verbose(_WINDOWS("DirectDraw: Mode selected = %4dx%4d@%3dHz\n"), dd->width, dd->height, dd->refresh); }
d3d *drawd3d8_init(void) { direct3dcreate8_ptr direct3dcreate8; HINSTANCE dllhandle; IDirect3D8 *d3d8; d3d *d3dptr; // dynamically grab the create function from d3d8.dll dllhandle = LoadLibrary(TEXT("d3d8.dll")); if (dllhandle == NULL) { mame_printf_verbose(_WINDOWS("Direct3D: Unable to access d3d8.dll\n")); return NULL; } // import the create function direct3dcreate8 = (direct3dcreate8_ptr)GetProcAddress(dllhandle, "Direct3DCreate8"); if (direct3dcreate8 == NULL) { mame_printf_verbose(_WINDOWS("Direct3D: Unable to find Direct3DCreate8\n")); FreeLibrary(dllhandle); dllhandle = NULL; return NULL; } // create our core direct 3d object d3d8 = (*direct3dcreate8)(D3D_SDK_VERSION); if (d3d8 == NULL) { mame_printf_verbose(_WINDOWS("Direct3D: Error attempting to initialize Direct3D8\n")); FreeLibrary(dllhandle); dllhandle = NULL; return NULL; } // allocate an object to hold our data d3dptr = global_alloc(d3d); d3dptr->version = 8; d3dptr->d3dobj = d3d8; d3dptr->dllhandle = dllhandle; set_interfaces(d3dptr); mame_printf_verbose(_WINDOWS("Direct3D: Using Direct3D 8\n")); return d3dptr; }
int drawdd_init(running_machine &machine, win_draw_callbacks *callbacks) { // dynamically grab the create function from ddraw.dll dllhandle = LoadLibrary(TEXT("ddraw.dll")); if (dllhandle == NULL) { osd_printf_verbose(_WINDOWS("DirectDraw: Unable to access ddraw.dll\n")); return 1; } // import the create function directdrawcreateex = (directdrawcreateex_ptr)GetProcAddress(dllhandle, "DirectDrawCreateEx"); if (directdrawcreateex == NULL) { osd_printf_verbose(_WINDOWS("DirectDraw: Unable to find DirectDrawCreateEx\n")); FreeLibrary(dllhandle); dllhandle = NULL; return 1; } // import the enumerate function directdrawenumerateex = (directdrawenumerateex_ptr)GetProcAddress(dllhandle, "DirectDrawEnumerateExA"); if (directdrawenumerateex == NULL) { osd_printf_verbose(_WINDOWS("DirectDraw: Unable to find DirectDrawEnumerateExA\n")); FreeLibrary(dllhandle); dllhandle = NULL; return 1; } // fill in the callbacks memset(callbacks, 0, sizeof(*callbacks)); callbacks->exit = drawdd_exit; callbacks->window_init = drawdd_window_init; callbacks->window_get_primitives = drawdd_window_get_primitives; callbacks->window_draw = drawdd_window_draw; callbacks->window_destroy = drawdd_window_destroy; osd_printf_verbose(_WINDOWS("DirectDraw: Using DirectDraw 7\n")); return 0; }
static void sound_exit(running_machine &machine) { // kill the buffers and dsound dsound_destroy_buffers(); dsound_kill(); // print out over/underflow stats if (buffer_overflows || buffer_underflows) mame_printf_verbose(_WINDOWS("Sound: buffer overflows=%d underflows=%d\n"), buffer_overflows, buffer_underflows); LOG(("Sound buffer: overflows=%d underflows=%d\n", buffer_overflows, buffer_underflows)); }
static int ddraw_create(win_window_info *window) { dd_info *dd = (dd_info *)window->drawdata; HRESULT result; int verify; // if a device exists, free it if (dd->ddraw != NULL) ddraw_delete(window); // create the DirectDraw object result = (*directdrawcreateex)(dd->adapter_ptr, (LPVOID *)&dd->ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during DirectDrawCreateEx call\n"), (int)result); goto error; } // verify the caps verify = ddraw_verify_caps(dd); if (verify == 2) { osd_printf_error(_WINDOWS("DirectDraw: Error - Device does not meet minimum requirements for DirectDraw rendering\n")); goto error; } if (verify == 1) osd_printf_verbose(_WINDOWS("DirectDraw: Warning - Device may not perform well for DirectDraw rendering\n")); // set the cooperative level // for non-window modes, we will use full screen here result = IDirectDraw7_SetCooperativeLevel(dd->ddraw, win_window_list->hwnd, DDSCL_SETFOCUSWINDOW); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(FOCUSWINDOW) call\n"), (int)result); goto error; } result = IDirectDraw7_SetCooperativeLevel(dd->ddraw, window->hwnd, DDSCL_SETDEVICEWINDOW | (window->fullscreen ? DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE : DDSCL_NORMAL)); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(DEVICEWINDOW) call\n"), (int)result); goto error; } // full screen mode: set the resolution if (window->fullscreen && video_config.switchres) { result = IDirectDraw7_SetDisplayMode(dd->ddraw, dd->width, dd->height, 32, dd->refresh, 0); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X attempting to set video mode %dx%d@%d call\n"), (int)result, dd->width, dd->height, dd->refresh); goto error; } } return ddraw_create_surfaces(window); error: ddraw_delete(window); return 1; }
static int ddraw_verify_caps(dd_info *dd) { int retval = 0; HRESULT result; // get the capabilities dd->ddcaps.dwSize = sizeof(dd->ddcaps); dd->helcaps.dwSize = sizeof(dd->helcaps); result = IDirectDraw7_GetCaps(dd->ddraw, &dd->ddcaps, &dd->helcaps); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during IDirectDraw7_GetCaps call\n"), (int)result); return 1; } // determine if hardware stretching is available if ((dd->ddcaps.dwCaps & DDCAPS_BLTSTRETCH) == 0) { osd_printf_verbose(_WINDOWS("DirectDraw: Warning - Device does not support hardware stretching\n")); retval = 1; } return retval; }
static void get_adapter_for_monitor(dd_info *dd, win_monitor_info *monitor) { monitor_enum_info einfo; HRESULT result; // try to find our monitor memset(&einfo, 0, sizeof(einfo)); einfo.monitor = monitor; result = (*directdrawenumerateex)(monitor_enum_callback, &einfo, DDENUM_ATTACHEDSECONDARYDEVICES); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during DirectDrawEnumerateEx call\n"), (int)result); // set up the adapter if (einfo.foundit && einfo.guid_ptr != NULL) { dd->adapter = einfo.guid; dd->adapter_ptr = &dd->adapter; } else dd->adapter_ptr = NULL; }
static int drawdd_window_init(win_window_info *window) { dd_info *dd; // allocate memory for our structures dd = global_alloc_clear(dd_info); window->drawdata = dd; // configure the adapter for the mode we want if (config_adapter_mode(window)) goto error; // create the ddraw object if (ddraw_create(window)) goto error; return 0; error: drawdd_window_destroy(window); osd_printf_error(_WINDOWS("Unable to initialize DirectDraw.\n")); return 1; }
static void blit_to_primary(win_window_info *window, int srcwidth, int srcheight) { dd_info *dd = (dd_info *)window->drawdata; IDirectDrawSurface7 *target = (dd->back != NULL) ? dd->back : dd->primary; win_monitor_info *monitor = winwindow_video_window_monitor(window, NULL); DDBLTFX blitfx = { sizeof(DDBLTFX) }; RECT clear, outer, dest, source; INT32 dstwidth, dstheight; HRESULT result; // compute source rect source.left = source.top = 0; source.right = srcwidth; source.bottom = srcheight; // compute outer rect -- windowed version if (!window->fullscreen) { GetClientRect(window->hwnd, &outer); ClientToScreen(window->hwnd, &((LPPOINT)&outer)[0]); ClientToScreen(window->hwnd, &((LPPOINT)&outer)[1]); // adjust to be relative to the monitor outer.left -= monitor->info.rcMonitor.left; outer.right -= monitor->info.rcMonitor.left; outer.top -= monitor->info.rcMonitor.top; outer.bottom -= monitor->info.rcMonitor.top; } // compute outer rect -- full screen version else { calc_fullscreen_margins(window, dd->primarydesc.dwWidth, dd->primarydesc.dwHeight, &outer); } // if we're respecting the aspect ratio, we need to adjust to fit dstwidth = rect_width(&outer); dstheight = rect_height(&outer); if (!video_config.hwstretch) { // trim the source if necessary if (rect_width(&outer) < srcwidth) { source.left += (srcwidth - rect_width(&outer)) / 2; source.right = source.left + rect_width(&outer); } if (rect_height(&outer) < srcheight) { source.top += (srcheight - rect_height(&outer)) / 2; source.bottom = source.top + rect_height(&outer); } // match the destination and source sizes dstwidth = srcwidth = source.right - source.left; dstheight = srcheight = source.bottom - source.top; } else if (video_config.keepaspect) { // compute the appropriate visible area window->target->compute_visible_area(rect_width(&outer), rect_height(&outer), winvideo_monitor_get_aspect(monitor), window->target->orientation(), dstwidth, dstheight); } // center within dest.left = outer.left + (rect_width(&outer) - dstwidth) / 2; dest.right = dest.left + dstwidth; dest.top = outer.top + (rect_height(&outer) - dstheight) / 2; dest.bottom = dest.top + dstheight; // compare against last destination; if different, force a redraw if (dest.left != dd->lastdest.left || dest.right != dd->lastdest.right || dest.top != dd->lastdest.top || dest.bottom != dd->lastdest.bottom) { dd->lastdest = dest; update_outer_rects(dd); } // clear outer rects if we need to if (dd->clearouter != 0) { dd->clearouter--; // clear the left edge if (dest.left > outer.left) { clear = outer; clear.right = dest.left; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X clearing the screen\n"), (int)result); } // clear the right edge if (dest.right < outer.right) { clear = outer; clear.left = dest.right; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X clearing the screen\n"), (int)result); } // clear the top edge if (dest.top > outer.top) { clear = outer; clear.bottom = dest.top; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X clearing the screen\n"), (int)result); } // clear the bottom edge if (dest.bottom < outer.bottom) { clear = outer; clear.top = dest.bottom; result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X clearing the screen\n"), (int)result); } } // do the blit result = IDirectDrawSurface7_Blt(target, &dest, dd->blit, &source, DDBLT_WAIT, NULL); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X blitting to the screen\n"), (int)result); // page flip if triple buffered if (window->fullscreen && dd->back != NULL) { result = IDirectDrawSurface7_Flip(dd->primary, NULL, DDFLIP_WAIT); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X waiting for VBLANK\n"), (int)result); } }
static HRESULT dsound_create_buffers(void) { HRESULT result; void *buffer; DWORD locked; // create a buffer desc for the primary buffer memset(&primary_desc, 0, sizeof(primary_desc)); primary_desc.dwSize = sizeof(primary_desc); primary_desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; primary_desc.lpwfxFormat = NULL; // create the primary buffer result = IDirectSound_CreateSoundBuffer(dsound, &primary_desc, &primary_buffer, NULL); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error creating primary DirectSound buffer: %08x\n"), (UINT32)result); goto error; } // attempt to set the primary format result = IDirectSoundBuffer_SetFormat(primary_buffer, &stream_format); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error setting primary DirectSound buffer format: %08x\n"), (UINT32)result); goto error; } // get the primary format result = IDirectSoundBuffer_GetFormat(primary_buffer, &primary_format, sizeof(primary_format), NULL); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error getting primary DirectSound buffer format: %08x\n"), (UINT32)result); goto error; } mame_printf_verbose(_WINDOWS("DirectSound: Primary buffer: %d Hz, %d bits, %d channels\n"), (int)primary_format.nSamplesPerSec, (int)primary_format.wBitsPerSample, (int)primary_format.nChannels); // create a buffer desc for the stream buffer memset(&stream_desc, 0, sizeof(stream_desc)); stream_desc.dwSize = sizeof(stream_desc); stream_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY; stream_desc.dwBufferBytes = stream_buffer_size; stream_desc.lpwfxFormat = &stream_format; // create the stream buffer result = IDirectSound_CreateSoundBuffer(dsound, &stream_desc, &stream_buffer, NULL); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error creating DirectSound stream buffer: %08x\n"), (UINT32)result); goto error; } // lock the buffer result = IDirectSoundBuffer_Lock(stream_buffer, 0, stream_buffer_size, &buffer, &locked, NULL, NULL, 0); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error locking DirectSound stream buffer: %08x\n"), (UINT32)result); goto error; } // clear the buffer and unlock it memset(buffer, 0, locked); IDirectSoundBuffer_Unlock(stream_buffer, buffer, locked, NULL, 0); return DS_OK; // error handling error: dsound_destroy_buffers(); return result; }
static void compute_blit_surface_size(win_window_info *window) { dd_info *dd = (dd_info *)window->drawdata; INT32 newwidth, newheight; int xscale, yscale; RECT client; // start with the minimum size window->target->compute_minimum_size(newwidth, newheight); // get the window's client rectangle GetClientRect(window->hwnd, &client); // hardware stretch case: apply prescale if (video_config.hwstretch) { int prescale = (video_config.prescale < 1) ? 1 : video_config.prescale; // clamp the prescale to something smaller than the target bounds xscale = prescale; while (xscale > 1 && newwidth * xscale > rect_width(&client)) xscale--; yscale = prescale; while (yscale > 1 && newheight * yscale > rect_height(&client)) yscale--; } // non stretch case else { INT32 target_width = rect_width(&client); INT32 target_height = rect_height(&client); float desired_aspect = 1.0f; // compute the appropriate visible area if we're trying to keepaspect if (video_config.keepaspect) { win_monitor_info *monitor = winwindow_video_window_monitor(window, NULL); window->target->compute_visible_area(target_width, target_height, winvideo_monitor_get_aspect(monitor), window->target->orientation(), target_width, target_height); desired_aspect = (float)target_width / (float)target_height; } // compute maximum integral scaling to fit the window xscale = (target_width + 2) / newwidth; yscale = (target_height + 2) / newheight; // try a little harder to keep the aspect ratio if desired if (video_config.keepaspect) { // if we could stretch more in the X direction, and that makes a better fit, bump the xscale while (newwidth * (xscale + 1) <= rect_width(&client) && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) xscale++; // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale while (newheight * (yscale + 1) <= rect_height(&client) && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) yscale++; // now that we've maxed out, see if backing off the maximally stretched one makes a better fit if (rect_width(&client) - newwidth * xscale < rect_height(&client) - newheight * yscale) { while (xscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect)) xscale--; } else { while (yscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect)) yscale--; } } } // ensure at least a scale factor of 1 if (xscale == 0) xscale = 1; if (yscale == 0) yscale = 1; // apply the final scale newwidth *= xscale; newheight *= yscale; if (newwidth != dd->blitwidth || newheight != dd->blitheight) { // force some updates update_outer_rects(dd); osd_printf_verbose(_WINDOWS("DirectDraw: New blit size = %dx%d\n"), newwidth, newheight); } dd->blitwidth = newwidth; dd->blitheight = newheight; }
d3d *drawd3d9_init(void) { direct3dcreate9_ptr direct3dcreate9; HINSTANCE dllhandle; IDirect3D9 *d3d9; d3d *d3dptr; bool post_available = true; // dynamically grab the create function from d3d9.dll dllhandle = LoadLibrary(TEXT("d3d9.dll")); if (dllhandle == NULL) { mame_printf_verbose(_WINDOWS("Direct3D: Unable to access d3d9.dll\n")); return NULL; } // import the create function direct3dcreate9 = (direct3dcreate9_ptr)GetProcAddress(dllhandle, "Direct3DCreate9"); if (direct3dcreate9 == NULL) { mame_printf_verbose(_WINDOWS("Direct3D: Unable to find Direct3DCreate9\n")); FreeLibrary(dllhandle); dllhandle = NULL; return NULL; } // create our core direct 3d object d3d9 = (*direct3dcreate9)(D3D_SDK_VERSION); if (d3d9 == NULL) { mame_printf_verbose(_WINDOWS("Direct3D: Error attempting to initialize Direct3D9\n")); FreeLibrary(dllhandle); dllhandle = NULL; return NULL; } // dynamically grab the shader load function from d3dx9.dll HINSTANCE fxhandle = LoadLibrary(TEXT("d3dx9_43.dll")); if (fxhandle == NULL) { post_available = false; mame_printf_verbose(_WINDOWS("Direct3D: Warning - Unable to access d3dx9_43.dll; disabling post-effect rendering\n")); } // import the create function if(post_available) { g_load_effect = (direct3dx9_loadeffect_ptr)GetProcAddress(fxhandle, "D3DXCreateEffectFromFileW"); if (g_load_effect == NULL) { printf("Direct3D: Unable to find D3DXCreateEffectFromFileW\n"); FreeLibrary(dllhandle); fxhandle = NULL; dllhandle = NULL; return NULL; } } else { g_load_effect = NULL; post_available = false; mame_printf_verbose(_WINDOWS("Direct3D: Warning - Unable to get a handle to D3DXCreateEffectFromFileW; disabling post-effect rendering\n")); } // allocate an object to hold our data d3dptr = global_alloc(d3d); d3dptr->version = 9; d3dptr->d3dobj = d3d9; d3dptr->dllhandle = dllhandle; d3dptr->post_fx_available = post_available; set_interfaces(d3dptr); mame_printf_verbose(_WINDOWS("Direct3D: Using Direct3D 9\n")); return d3dptr; }
static int config_adapter_mode(win_window_info *window) { DDDEVICEIDENTIFIER2 identifier; dd_info *dd = (dd_info *)window->drawdata; HRESULT result; // choose the monitor number get_adapter_for_monitor(dd, window->monitor); // create a temporary DirectDraw object result = (*directdrawcreateex)(dd->adapter_ptr, (LPVOID *)&dd->ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X during DirectDrawCreateEx call\n"), (int)result); return 1; } // get the identifier result = IDirectDraw7_GetDeviceIdentifier(dd->ddraw, &identifier, 0); if (result != DD_OK) { osd_printf_error(_WINDOWS("Error getting identifier for device\n")); return 1; } osd_printf_verbose(_WINDOWS("DirectDraw: Configuring device %s\n"), identifier.szDescription); // get the current display mode memset(&dd->origmode, 0, sizeof(dd->origmode)); dd->origmode.dwSize = sizeof(dd->origmode); result = IDirectDraw7_GetDisplayMode(dd->ddraw, &dd->origmode); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X getting current display mode\n"), (int)result); IDirectDraw7_Release(dd->ddraw); return 1; } // choose a resolution: full screen mode case if (window->fullscreen) { // default to the current mode exactly dd->width = dd->origmode.dwWidth; dd->height = dd->origmode.dwHeight; dd->refresh = dd->origmode.dwRefreshRate; // if we're allowed to switch resolutions, override with something better if (video_config.switchres) pick_best_mode(window); } // release the DirectDraw object IDirectDraw7_Release(dd->ddraw); dd->ddraw = NULL; // if we're not changing resolutions, make sure we have a resolution we can handle if (!window->fullscreen || !video_config.switchres) { switch (dd->origmode.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: case 0x000000ff: case 0xf800: case 0x7c00: break; default: osd_printf_verbose(_WINDOWS("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n"), (int)dd->origmode.ddpfPixelFormat.dwRBitMask, (int)dd->origmode.ddpfPixelFormat.dwGBitMask, (int)dd->origmode.ddpfPixelFormat.dwBBitMask); return 1; } } return 0; }
static int ddraw_create_surfaces(win_window_info *window) { dd_info *dd = (dd_info *)window->drawdata; HRESULT result; // make a description of the primary surface memset(&dd->primarydesc, 0, sizeof(dd->primarydesc)); dd->primarydesc.dwSize = sizeof(dd->primarydesc); dd->primarydesc.dwFlags = DDSD_CAPS; dd->primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // for triple-buffered full screen mode, allocate flipping surfaces if (window->fullscreen && video_config.triplebuf) { dd->primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; dd->primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; dd->primarydesc.dwBackBufferCount = 2; } // create the primary surface and report errors result = create_surface(dd, &dd->primarydesc, &dd->primary, "primary"); if (result != DD_OK) goto error; // full screen mode: get the back surface dd->back = NULL; if (window->fullscreen && video_config.triplebuf) { DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; result = IDirectDrawSurface7_GetAttachedSurface(dd->primary, &caps, &dd->back); if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X getting attached back surface\n"), (int)result); goto error; } } // now make a description of our blit surface, based on the primary surface if (dd->blitwidth == 0 || dd->blitheight == 0) compute_blit_surface_size(window); dd->blitdesc = dd->primarydesc; dd->blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; dd->blitdesc.dwWidth = dd->blitwidth; dd->blitdesc.dwHeight = dd->blitheight; dd->blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; // then create the blit surface, fall back to system memory if video mem doesn't work result = create_surface(dd, &dd->blitdesc, &dd->blit, "blit"); if (result != DD_OK) { dd->blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; result = create_surface(dd, &dd->blitdesc, &dd->blit, "blit"); } if (result != DD_OK) goto error; // create a memory buffer for offscreen drawing if (dd->membuffersize < dd->blitwidth * dd->blitheight * 4) { dd->membuffersize = dd->blitwidth * dd->blitheight * 4; global_free_array(dd->membuffer); dd->membuffer = global_alloc_array(UINT8, dd->membuffersize); } if (dd->membuffer == NULL) goto error; // create a clipper for windowed mode if (!window->fullscreen && create_clipper(window)) goto error; // full screen mode: set the gamma if (window->fullscreen) { // only set the gamma if it's not 1.0f windows_options &options = downcast<windows_options &>(window->machine().options()); float brightness = options.full_screen_brightness(); float contrast = options.full_screen_contrast(); float gamma = options.full_screen_gamma(); if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f) { // see if we can get a GammaControl object result = IDirectDrawSurface_QueryInterface(dd->primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&dd->gamma); if (result != DD_OK) { osd_printf_warning(_WINDOWS("DirectDraw: Warning - device does not support full screen gamma correction.\n")); dd->gamma = NULL; } // proceed if we can if (dd->gamma != NULL) { DDGAMMARAMP ramp; int i; // create a standard ramp and set it for (i = 0; i < 256; i++) ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8; // attempt to set it result = IDirectDrawGammaControl_SetGammaRamp(dd->gamma, 0, &ramp); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X attempting to set gamma correction.\n"), (int)result); } } } // force some updates update_outer_rects(dd); return 0; error: ddraw_delete_surfaces(window); return 1; }
static HRESULT dsound_init(running_machine &machine) { HRESULT result; // create the DirectSound object result = DirectSoundCreate(NULL, &dsound, NULL); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error creating DirectSound: %08x\n"), (UINT32)result); goto error; } // get the capabilities dsound_caps.dwSize = sizeof(dsound_caps); result = IDirectSound_GetCaps(dsound, &dsound_caps); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error getting DirectSound capabilities: %08x\n"), (UINT32)result); goto error; } // set the cooperative level result = IDirectSound_SetCooperativeLevel(dsound, win_window_list->hwnd, DSSCL_PRIORITY); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error setting DirectSound cooperative level: %08x\n"), (UINT32)result); goto error; } // make a format description for what we want stream_format.wBitsPerSample = 16; stream_format.wFormatTag = WAVE_FORMAT_PCM; stream_format.nChannels = 2; stream_format.nSamplesPerSec = machine.sample_rate(); stream_format.nBlockAlign = stream_format.wBitsPerSample * stream_format.nChannels / 8; stream_format.nAvgBytesPerSec = stream_format.nSamplesPerSec * stream_format.nBlockAlign; // compute the buffer size based on the output sample rate stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * downcast<windows_options &>(machine.options()).audio_latency() / 10; stream_buffer_size = (stream_buffer_size / 1024) * 1024; if (stream_buffer_size < 1024) stream_buffer_size = 1024; LOG(("stream_buffer_size = %d\n", stream_buffer_size)); // create the buffers result = dsound_create_buffers(); if (result != DS_OK) goto error; // start playing result = IDirectSoundBuffer_Play(stream_buffer, 0, 0, DSBPLAY_LOOPING); if (result != DS_OK) { mame_printf_error(_WINDOWS("Error playing: %08x\n"), (UINT32)result); goto error; } return DS_OK; // error handling error: dsound_destroy_buffers(); dsound_kill(); return result; }
static int drawdd_window_draw(win_window_info *window, HDC dc, int update) { dd_info *dd = (dd_info *)window->drawdata; render_primitive *prim; int usemembuffer = FALSE; HRESULT result; // if we haven't been created, just punt if (dd == NULL) return 1; // if we're updating, remember to erase the outer stuff if (update) update_outer_rects(dd); // if we have a ddraw object, check the cooperative level if (ddraw_test_cooperative(window)) return 1; // get the size; if we're too small, delete the existing surfaces if (dd->blitwidth > dd->blitdesc.dwWidth || dd->blitheight > dd->blitdesc.dwHeight) ddraw_delete_surfaces(window); // if we need to create surfaces, do it now if (dd->blit == NULL && ddraw_create_surfaces(window) != 0) return 1; // select our surface and lock it result = IDirectDrawSurface7_Lock(dd->blit, NULL, &dd->blitdesc, DDLOCK_WAIT, NULL); if (result == DDERR_SURFACELOST) { osd_printf_verbose(_WINDOWS("DirectDraw: Lost surfaces; deleting and retrying next frame\n")); ddraw_delete_surfaces(window); return 1; } if (result != DD_OK) { osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X locking blit surface\n"), (int)result); return 1; } // render to it window->primlist->acquire_lock(); // scan the list of primitives for tricky stuff for (prim = window->primlist->first(); prim != NULL; prim = prim->next()) if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE || (prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32)) { usemembuffer = TRUE; break; } // if we're using the memory buffer, draw offscreen first and then copy if (usemembuffer) { int x, y; // based on the target format, use one of our standard renderers switch (dd->blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window->primlist, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window->primlist, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window->primlist, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window->primlist, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth); break; default: osd_printf_verbose(_WINDOWS("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n"), (int)dd->blitdesc.ddpfPixelFormat.dwRBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwGBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwBBitMask); break; } // handle copying to both 16bpp and 32bpp destinations for (y = 0; y < dd->blitheight; y++) { if (dd->blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) { UINT32 *src = (UINT32 *)dd->membuffer + y * dd->blitwidth; UINT32 *dst = (UINT32 *)((UINT8 *)dd->blitdesc.lpSurface + y * dd->blitdesc.lPitch); for (x = 0; x < dd->blitwidth; x++) *dst++ = *src++; } else if (dd->blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) { UINT16 *src = (UINT16 *)dd->membuffer + y * dd->blitwidth; UINT16 *dst = (UINT16 *)((UINT8 *)dd->blitdesc.lpSurface + y * dd->blitdesc.lPitch); for (x = 0; x < dd->blitwidth; x++) *dst++ = *src++; } } } // otherwise, draw directly else { // based on the target format, use one of our standard renderers switch (dd->blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window->primlist, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 4); break; case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window->primlist, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 4); break; case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window->primlist, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 2); break; case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window->primlist, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 2); break; default: osd_printf_verbose(_WINDOWS("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n"), (int)dd->blitdesc.ddpfPixelFormat.dwRBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwGBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwBBitMask); break; } } window->primlist->release_lock(); // unlock and blit result = IDirectDrawSurface7_Unlock(dd->blit, NULL); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X unlocking blit surface\n"), (int)result); // sync to VBLANK if ((video_config.waitvsync || video_config.syncrefresh) && window->machine().video().throttled() && (!window->fullscreen || dd->back == NULL)) { result = IDirectDraw7_WaitForVerticalBlank(dd->ddraw, DDWAITVB_BLOCKBEGIN, NULL); if (result != DD_OK) osd_printf_verbose(_WINDOWS("DirectDraw: Error %08X waiting for VBLANK\n"), (int)result); } // complete the blitting blit_to_primary(window, dd->blitwidth, dd->blitheight); return 0; }