int sound_sdl::init(const osd_options &options) { int n_channels = 2; int audio_latency; SDL_AudioSpec aspec, obtained; char audio_driver[16] = ""; if (LOG_SOUND) sound_log = fopen(SDLMAME_SOUND_LOG, "w"); // skip if sound disabled if (sample_rate() != 0) { if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { osd_printf_error("Could not initialize SDL %s\n", SDL_GetError()); return -1; } osd_printf_verbose("Audio: Start initialization\n"); #if (SDLMAME_SDL2) strncpy(audio_driver, SDL_GetCurrentAudioDriver(), sizeof(audio_driver)); #else SDL_AudioDriverName(audio_driver, sizeof(audio_driver)); #endif osd_printf_verbose("Audio: Driver is %s\n", audio_driver); sdl_xfer_samples = SDL_XFER_SAMPLES; stream_in_initialized = 0; stream_loop = 0; // set up the audio specs aspec.freq = sample_rate(); aspec.format = AUDIO_S16SYS; // keep endian independent aspec.channels = n_channels; aspec.samples = sdl_xfer_samples; aspec.callback = sdl_callback; aspec.userdata = this; if (SDL_OpenAudio(&aspec, &obtained) < 0) goto cant_start_audio; osd_printf_verbose("Audio: frequency: %d, channels: %d, samples: %d\n", obtained.freq, obtained.channels, obtained.samples); sdl_xfer_samples = obtained.samples; // pin audio latency audio_latency = MAX(MIN(m_audio_latency, MAX_AUDIO_LATENCY), 1); // compute the buffer sizes stream_buffer_size = (sample_rate() * 2 * sizeof(INT16) * (2 + audio_latency)) / 30; stream_buffer_size = (stream_buffer_size / 1024) * 1024; if (stream_buffer_size < 1024) stream_buffer_size = 1024; // create the buffers if (sdl_create_buffers()) goto cant_create_buffers; // set the startup volume set_mastervolume(attenuation); osd_printf_verbose("Audio: End initialization\n"); return 0; // error handling cant_create_buffers: cant_start_audio: osd_printf_verbose("Audio: Initialization failed. SDL error: %s\n", SDL_GetError()); return -1; } return 0; }
void m1comm_device::comm_tick() { if (m_linkenable == 0x01) { int frameStart = 0x0010; int frameOffset = 0x0000; int frameSize = 0x01c4; int dataSize = frameSize + 1; int togo = 0; int recv = 0; int idx = 0; bool isMaster = (m_shared[1] == 0x01); bool isSlave = (m_shared[1] == 0x02); bool isRelay = (m_shared[1] == 0x00); // if link not yet established... if (m_linkalive == 0x00) { // waiting... m_shared[0] = 0x05; // check rx socket if (!m_line_rx.is_open()) { osd_printf_verbose("M1COMM: listen on %s\n", m_localhost); m_line_rx.open(m_localhost); } // check tx socket if (!m_line_tx.is_open()) { osd_printf_verbose("M1COMM: connect to %s\n", m_remotehost); m_line_tx.open(m_remotehost); } // if both sockets are there check ring if ((m_line_rx.is_open()) && (m_line_tx.is_open())) { // try to read one messages recv = m_line_rx.read(m_buffer, dataSize); while (recv != 0) { // check if complete message if (recv == dataSize) { // check if message id idx = m_buffer[0]; // 0xFF - link id if (idx == 0xff) { if (isMaster) { // master gets first id and starts next state m_linkid = 0x01; m_linkcount = m_buffer[1]; m_linktimer = 0x01; } else if (isSlave || isRelay) { // slave gets own id if (isSlave) { m_buffer[1]++; m_linkid = m_buffer[1]; } // slave and relay forward message m_line_tx.write(m_buffer, dataSize); } } // 0xFE - link size else if (idx == 0xfe) { if (isSlave || isRelay) { m_linkcount = m_buffer[1]; // slave and relay forward message m_line_tx.write(m_buffer, dataSize); } // consider it done osd_printf_verbose("M1COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); m_linkalive = 0x01; m_zfg = 0x01; // write to shared mem m_shared[0] = 0x01; m_shared[2] = m_linkid; m_shared[3] = m_linkcount; } } else { // got only part of a message - read the rest (and drop it) // TODO: combine parts and push to "ring buffer" togo = dataSize - recv; while (togo > 0){ recv = m_line_rx.read(m_buffer, togo); togo -= recv; } osd_printf_verbose("M1COMM: dropped a message...\n"); } if (m_linkalive == 0x00) recv = m_line_rx.read(m_buffer, dataSize); else recv = 0; } // if we are master and link is not yet established if (isMaster && (m_linkalive == 0x00)) { // send first packet if (m_linktimer == 0x00) { m_buffer[0] = 0xff; m_buffer[1] = 0x01; m_line_tx.write(m_buffer, dataSize); } // send second packet else if (m_linktimer == 0x01) { m_buffer[0] = 0xfe; m_buffer[1] = m_linkcount; m_line_tx.write(m_buffer, dataSize); // consider it done osd_printf_verbose("M1COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); m_linkalive = 0x01; m_zfg = 0x01; // write to shared mem m_shared[0] = 0x01; m_shared[2] = m_linkid; m_shared[3] = m_linkcount; } else if (m_linktimer > 0x02) { // decrease delay timer m_linktimer--; if (m_linktimer == 0x02) m_linktimer = 0x00; } } } } // update "ring buffer" if link established if (m_linkalive == 0x01) { int togo = 0; // try to read one messages int recv = m_line_rx.read(m_buffer, dataSize); while (recv != 0) { // check if complete message if (recv == dataSize) { // check if valid id int idx = m_buffer[0]; if (idx > 0 && idx <= m_linkcount) { // if not our own message if (idx != m_linkid) { // save message to "ring buffer" frameOffset = frameStart + (idx * frameSize); for (int j = 0x00 ; j < frameSize ; j++) { m_shared[frameOffset + j] = m_buffer[1 + j]; } // forward message to other nodes m_line_tx.write(m_buffer, dataSize); } } else { if (!isMaster && idx == 0xf0){ // 0xF0 - master addional bytes for (int j = 0x06 ; j < 0x10 ; j++) { m_shared[j] = m_buffer[1 + j]; } // forward message to other nodes m_line_tx.write(m_buffer, dataSize); } } } else { // got only part of a message - read the rest (and drop it) // TODO: combine parts and push to "ring buffer" togo = dataSize - recv; while (togo > 0){ recv = m_line_rx.read(m_buffer, togo); togo -= recv; } osd_printf_verbose("M1COMM: dropped a message...\n"); } recv = m_line_rx.read(m_buffer, dataSize); } // update "ring buffer" if link established // live relay does not send data if (m_linkid != 0x00 && m_shared[5] != 0x00) { m_buffer[0] = m_linkid; frameOffset = frameStart + (m_linkid * frameSize); for (int j = 0x00 ; j < frameSize ; j++) { // push message to "ring buffer" m_shared[frameOffset + j] = m_shared[frameStart + j]; m_buffer[1 + j] = m_shared[frameStart + j]; } // push message to other nodes m_line_tx.write(m_buffer, dataSize); // master sends some additional status bytes if (isMaster){ m_buffer[0] = 0xf0; for (int j = 0x00 ; j < frameSize ; j++) { m_buffer[1 + j] = 0x00; } for (int j = 0x06 ; j < 0x10 ; j++) { m_buffer[1 + j] = m_shared[j]; } // push message to other nodes m_line_tx.write(m_buffer, dataSize); } } // clear 05 m_shared[5] = 0x00; } } }
int sdl_window_info::complete_create() { osd_dim temp(0,0); // clear out original mode. Needed on OSX if (fullscreen()) { // default to the current mode exactly temp = monitor()->position_size().dim(); // if we're allowed to switch resolutions, override with something better if (video_config.switchres) temp = pick_best_mode(); } else if (m_windowed_dim.width() > 0) { // if we have a remembered size force the new window size to it temp = m_windowed_dim; } else if (m_startmaximized) temp = get_max_bounds(video_config.keepaspect ); else temp = get_min_bounds(video_config.keepaspect ); // create the window ..... /* FIXME: On Ubuntu and potentially other Linux OS you should use * to disable panning. This has to be done before every invocation of mame. * * xrandr --output HDMI-0 --panning 0x0+0+0 --fb 0x0 * */ osd_printf_verbose("Enter sdl_info::create\n"); if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL)) { SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); /* FIXME: A reminder that gamma is wrong throughout MAME. Currently, SDL2.0 doesn't seem to * support the following attribute although my hardware lists GL_ARB_framebuffer_sRGB as an extension. * * SDL_GL_SetAttribute( SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1 ); * */ m_extra_flags = SDL_WINDOW_OPENGL; } else m_extra_flags = 0; #ifdef SDLMAME_MACOSX /* FIMXE: On OSX, SDL_WINDOW_FULLSCREEN_DESKTOP seems to be more reliable. * It however creates issues with white borders, i.e. the screen clear * does not work. This happens both with opengl and accel. */ #endif // We need to workaround an issue in SDL 2.0.4 for OS X where setting the // relative mode on the mouse in fullscreen mode makes mouse events stop // It is fixed in the latest revisions so we'll assume it'll be fixed // in the next public SDL release as well #if defined(SDLMAME_MACOSX) && SDL_VERSION_ATLEAST(2, 0, 2) // SDL_HINT_MOUSE_RELATIVE_MODE_WARP is introduced in 2.0.2 SDL_version linked; SDL_GetVersion(&linked); int revision = SDL_GetRevisionNumber(); // If we're running the exact version of SDL 2.0.4 (revision 10001) from the // SDL web site, we need to work around this issue and send the warp mode hint if (SDL_VERSION_EQUALS(linked, SDL_VERSIONNUM(2, 0, 4)) && revision == 10001) { osd_printf_verbose("Using warp mode for relative mouse in OS X SDL 2.0.4\n"); SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); } #endif // create the SDL window // soft driver also used | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_MOUSE_FOCUS m_extra_flags |= (fullscreen() ? /*SDL_WINDOW_BORDERLESS |*/ SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE); #if defined(SDLMAME_WIN32) SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); #endif // get monitor work area for centering osd_rect work = monitor()->usuable_position_size(); // create the SDL window auto sdlwindow = SDL_CreateWindow(m_title, work.left() + (work.width() - temp.width()) / 2, work.top() + (work.height() - temp.height()) / 2, temp.width(), temp.height(), m_extra_flags); //window().sdl_window() = SDL_CreateWindow(window().m_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, // width, height, m_extra_flags); if (sdlwindow == nullptr ) { if (renderer().has_flags(osd_renderer::FLAG_NEEDS_OPENGL)) osd_printf_error("OpenGL not supported on this driver: %s\n", SDL_GetError()); else osd_printf_error("Window creation failed: %s\n", SDL_GetError()); return 1; } set_platform_window(sdlwindow); if (fullscreen() && video_config.switchres) { SDL_DisplayMode mode; //SDL_GetCurrentDisplayMode(window().monitor()->handle, &mode); SDL_GetWindowDisplayMode(platform_window(), &mode); m_original_mode->mode = mode; mode.w = temp.width(); mode.h = temp.height(); if (m_win_config.refresh) mode.refresh_rate = m_win_config.refresh; SDL_SetWindowDisplayMode(platform_window(), &mode); // Try to set mode #ifndef SDLMAME_WIN32 /* FIXME: Warp the mouse to 0,0 in case a virtual desktop resolution * is in place after the mode switch - which will most likely be the case * This is a hack to work around a deficiency in SDL2 */ SDL_WarpMouseInWindow(platform_window(), 1, 1); #endif } else { //SDL_SetWindowDisplayMode(window().sdl_window(), nullptr); // Use desktop } // show window SDL_ShowWindow(platform_window()); //SDL_SetWindowFullscreen(window->sdl_window(), 0); //SDL_SetWindowFullscreen(window->sdl_window(), window->fullscreen()); SDL_RaiseWindow(platform_window()); #ifdef SDLMAME_WIN32 if (fullscreen()) SDL_SetWindowGrab(platform_window(), SDL_TRUE); #endif // set main window if (m_index > 0) { for (auto w : osd_common_t::s_window_list) { if (w->m_index == 0) { set_main_window(std::dynamic_pointer_cast<osd_window>(w)); break; } } } else { // We must be the main window set_main_window(shared_from_this()); } // update monitor resolution after mode change to ensure proper pixel aspect monitor()->refresh(); if (fullscreen() && video_config.switchres) monitor()->update_resolution(temp.width(), temp.height()); // initialize the drawing backend if (renderer().create()) return 1; // Make sure we have a consistent state SDL_ShowCursor(0); SDL_ShowCursor(1); return 0; }
bool sdl_osd_interface::window_init() { osd_printf_verbose("Enter sdlwindow_init\n"); // determine if we are using multithreading or not multithreading_enabled = options().multithreading(); // get the main thread ID before anything else main_threadid = SDL_ThreadID(); // if multithreading, create a thread to run the windows if (multithreading_enabled) { // create a thread to run the windows from work_queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_IO); if (work_queue == NULL) return false; osd_work_item_queue(work_queue, &sdlwindow_thread_id, NULL, WORK_ITEM_FLAG_AUTO_RELEASE); sdlwindow_sync(); } else { // otherwise, treat the window thread as the main thread //window_threadid = main_threadid; sdlwindow_thread_id(NULL, 0); } // initialize the drawers #if USE_OPENGL if (video_config.mode == VIDEO_MODE_OPENGL) { if (drawogl_init(machine(), &draw)) video_config.mode = VIDEO_MODE_SOFT; } #endif #if SDLMAME_SDL2 if (video_config.mode == VIDEO_MODE_SDL2ACCEL) { if (drawsdl2_init(machine(), &draw)) video_config.mode = VIDEO_MODE_SOFT; } #endif #ifdef USE_BGFX if (video_config.mode == VIDEO_MODE_BGFX) { if (drawbgfx_init(machine(), &draw)) video_config.mode = VIDEO_MODE_SOFT; } #endif if (video_config.mode == VIDEO_MODE_SOFT) { if (drawsdl_init(&draw)) return false; } #if SDLMAME_SDL2 /* We may want to set a number of the hints SDL2 provides. * The code below will document which hints were set. */ const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION, SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS, SDL_HINT_RENDER_SCALE_QUALITY, SDL_HINT_RENDER_VSYNC, SDL_HINT_VIDEO_X11_XVIDMODE, SDL_HINT_VIDEO_X11_XINERAMA, SDL_HINT_VIDEO_X11_XRANDR, SDL_HINT_GRAB_KEYBOARD, SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_HINT_IDLE_TIMER_DISABLED, SDL_HINT_ORIENTATIONS, SDL_HINT_XINPUT_ENABLED, SDL_HINT_GAMECONTROLLERCONFIG, SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_HINT_ALLOW_TOPMOST, SDL_HINT_TIMER_RESOLUTION, #if SDL_VERSION_ATLEAST(2, 0, 2) SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_HINT_VIDEO_ALLOW_SCREENSAVER, SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_MOUSE_RELATIVE_MODE_WARP, #endif #if SDL_VERSION_ATLEAST(2, 0, 3) SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_HINT_VIDEO_HIGHDPI_DISABLED, SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL, SDL_HINT_WINRT_HANDLE_BACK_BUTTON, #endif NULL }; osd_printf_verbose("\nHints:\n"); for (int i = 0; hints[i] != NULL; i++) osd_printf_verbose("\t%-40s %s\n", hints[i], SDL_GetHint(hints[i])); #endif // set up the window list last_window_ptr = &sdl_window_list; osd_printf_verbose("Leave sdlwindow_init\n"); return true; }
chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int current_cylinder, int current_head) { if (TRACE_RWTRACK) osd_printf_verbose("%s: write back (c=%d,h=%d) to CHD\n", tag(), current_cylinder, current_head); uint8_t buffer[16384]; // for header or sector content int bytepos = 0; int state = SEARCH_A1; int count = 0; int pos = 0; uint16_t crc = 0; uint8_t byte; bool search_header = true; int ident = 0; int cylinder = 0; int head = 0; int sector = 0; int size = 0; int headerpos = 0; int interleave = 0; int interleave_prec = -1; bool check_interleave = true; bool check_skew = true; int gap1 = 0; int ecctype = 0; // if (current_cylinder==0 && current_head==0) showtrack(trackimage, tracksize); // If we want to detect gaps, we only do it on cylinder 0, head 0 // This makes it safer to detect the header length // (There is indeed some chance that we falsely assume a header length of 4 // because the two bytes behind happen to be a valid CRC value) if (save_param(MFMHD_GAP1) && current_cylinder==0 && current_head==0) { m_param.gap1 = 0; m_param.gap2 = 0; m_param.gap3 = 0; m_param.sync = 0; // 4-byte headers are used for the IBM-AT format // 5-byte headers are used in other formats m_param.headerlen = 4; m_param.ecctype = 0; } // AT format implies 512 bytes per sector int sector_length = 512; // Only check once bool countgap1 = (m_param.gap1==0); bool countgap2 = false; bool countgap3 = false; bool countsync = false; chd_error chdstate = CHDERR_NONE; if (TRACE_IMAGE) { for (int i=0; i < tracksize; i++) { if ((i % 16)==0) osd_printf_verbose("\n%04x: ", i); osd_printf_verbose("%02x ", (m_param.encoding==MFM_BITS || m_param.encoding==MFM_BYTE)? mfm_decode(trackimage[i]) : (trackimage[i]&0xff)); } osd_printf_verbose("\n"); } // We have to go through the bytes of the track and save a sector as soon as one shows up while (bytepos < tracksize) { // Decode the next 16 bits if (m_param.encoding==MFM_BITS || m_param.encoding==MFM_BYTE) { byte = mfm_decode(trackimage[bytepos]); } else byte = (trackimage[bytepos] & 0xff); switch (state) { case SEARCH_A1: // Counting gaps and sync if (countgap2) { if (byte == 0x4e) m_param.gap2++; else if (byte == 0) { countsync = true; countgap2 = false; } } if (countsync) { if (byte == 0) m_param.sync++; else countsync = false; } if (countgap3) { if (byte != 0x00 || m_param.gap3 < 4) m_param.gap3++; else countgap3 = false; } if (((m_param.encoding==MFM_BITS || m_param.encoding==MFM_BYTE) && trackimage[bytepos]==0x4489) || (m_param.encoding==SEPARATED && trackimage[bytepos]==0x0aa1) || (m_param.encoding==SEPARATED_SIMPLE && trackimage[bytepos]==0xffa1)) { state = FOUND_A1; count = (search_header? m_param.headerlen : (sector_length+1)) + 2; crc = 0x443b; // init value with a1 pos = 0; } bytepos++; break; case FOUND_A1: crc = ccitt_crc16_one(crc, byte); // osd_printf_verbose("%s: MFM HD: Byte = %02x, CRC=%04x\n", tag(), byte, crc); // Put byte into buffer // but not the data mark and the CRC if (search_header || (count > 2 && count < sector_length+3)) buffer[pos++] = byte; // Stop counting gap1 if (search_header && countgap1) { gap1 = bytepos-1; countgap1 = false; } if (--count == 0) { if (crc==0) { if (search_header) { // Found a header ident = buffer[0]; cylinder = buffer[1]; // For non-PC-AT formats, highest three bits are in the head field if (m_param.headerlen == 5) cylinder |= ((buffer[2]&0x70)<<4); else { osd_printf_verbose("%s: Unexpected header size: %d, cylinder=%d, position=%04x\n", tag(), m_param.headerlen, cylinder, bytepos); showtrack(trackimage, tracksize); } head = buffer[2] & 0x0f; sector = buffer[3]; int identexp = cylinder_to_ident(cylinder); if (identexp != ident) { osd_printf_verbose("%s: Field error; ident = %02x (expected %02x) for sector chs=(%d,%d,%d)\n", tag(), ident, identexp, cylinder, head, sector); } if (cylinder != current_cylinder) { osd_printf_verbose("%s: Sector header of sector %d defines cylinder = %02x (should be %02x)\n", tag(), sector, cylinder, current_cylinder); } if (head != current_head) { osd_printf_verbose("%s: Sector header of sector %d defines head = %02x (should be %02x)\n", tag(), sector, head, current_head); } // Check skew // We compare the beginning of this track with the track on the next head and the track on the next cylinder if (check_skew && cylinder < 2 && head < 2) { m_secnumber[cylinder*2 + head] = sector; check_skew=false; } // Count the sectors for the interleave if (check_interleave) { if (interleave_prec == -1) interleave_prec = sector; else { if (sector == interleave_prec+1) check_interleave = false; interleave++; } } if (interleave == 0) interleave = sector - buffer[3]; // When we have 4-byte headers, the sector length is 512 bytes if (m_param.headerlen == 5) { size = buffer[4]; sector_length = 128 << (size&0x07); ecctype = (size&0xf0)>>4; } search_header = false; if (TRACE_DETAIL) osd_printf_verbose("%s: Found sector chs=(%d,%d,%d)\n", tag(), cylinder, head, sector); headerpos = pos; // Start the GAP2 counter (if not already determined) if (m_param.gap2==0) countgap2 = true; } else { // Sector contents // Write the sectors to the CHD int lbaposition = chs_to_lba(cylinder, head, sector); if (lbaposition>=0) { if (TRACE_DETAIL) osd_printf_verbose("%s: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), current_cylinder, current_head, sector); chdstate = chdfile->write_units(chs_to_lba(current_cylinder, current_head, sector), buffer); if (chdstate != CHDERR_NONE) { osd_printf_verbose("%s: Write error while writing sector chs=(%d,%d,%d)\n", tag(), cylinder, head, sector); } } else { osd_printf_verbose("%s: Invalid CHS data in track image: (%d,%d,%d); not saving to CHD\n", tag(), cylinder, head, sector); } if (m_param.gap3==0) countgap3 = true; search_header = true; } } else { // Let's test for a 5-byte header if (search_header && m_param.headerlen==4 && current_cylinder==0 && current_head==0) { if (TRACE_DETAIL) osd_printf_verbose("%s: CRC error for 4-byte header; trying 5 bytes\n", tag()); m_param.headerlen=5; count = 1; bytepos++; break; } else { osd_printf_verbose("%s: CRC error in %s of (%d,%d,%d)\n", tag(), search_header? "header" : "data", cylinder, head, sector); search_header = true; } } // search next A1 state = SEARCH_A1; if (!search_header && (pos - headerpos) > 30) { osd_printf_verbose("%s: Error; missing DAM; searching next header\n", tag()); search_header = true; } }
osd_dim sdl_window_info::pick_best_mode() { int minimum_width, minimum_height, target_width, target_height; int i; float size_score, best_score = 0.0f; int best_width = 0, best_height = 0; SDL_Rect **modes; // determine the minimum width/height for the selected target m_target->compute_minimum_size(minimum_width, minimum_height); // use those as the target for now target_width = minimum_width * MAX(1, prescale()); target_height = minimum_height * MAX(1, prescale()); // if we're not stretching, allow some slop on the minimum since we can handle it { minimum_width -= 4; minimum_height -= 4; } #if 1 // defined(SDLMAME_WIN32) /* * We need to do this here. If SDL_ListModes is * called in init_monitors, the call will crash * on win32 */ modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_DOUBLEBUF); #else modes = window->m_monitor->modes; #endif if (modes == (SDL_Rect **)0) { osd_printf_error("SDL: No modes available?!\n"); exit(-1); } else if (modes == (SDL_Rect **)-1) // all modes are possible { return osd_dim(m_win_config.width, m_win_config.height); } else { for (i = 0; modes[i]; ++i) { // compute initial score based on difference between target and current size_score = 1.0f / (1.0f + fabsf((INT32)modes[i]->w - target_width) + fabsf((INT32)modes[i]->h - target_height)); // if the mode is too small, give a big penalty if (modes[i]->w < minimum_width || modes[i]->h < minimum_height) size_score *= 0.01f; // if mode is smaller than we'd like, it only scores up to 0.1 if (modes[i]->w < target_width || modes[i]->h < target_height) size_score *= 0.1f; // if we're looking for a particular mode, that's a winner if (modes[i]->w == m_win_config.width && modes[i]->h == m_win_config.height) size_score = 2.0f; osd_printf_verbose("%4dx%4d -> %f\n", (int)modes[i]->w, (int)modes[i]->h, size_score); // best so far? if (size_score > best_score) { best_score = size_score; best_width = modes[i]->w; best_height = modes[i]->h; } } } return osd_dim(best_width, best_height); }
//------------------------------------------------- // initialize story.dat index //------------------------------------------------- void datfile_manager::init_storyinfo() { int swcount = 0; int count = index_datafile(m_storyidx, swcount); osd_printf_verbose("Story.dat games found = %i\n", count); }
void sdl_monitor_info::refresh() { #if (SDLMAME_SDL2) SDL_DisplayMode dmode; #if defined(SDLMAME_WIN32) SDL_GetDesktopDisplayMode(m_handle, &dmode); #else SDL_GetCurrentDisplayMode(m_handle, &dmode); #endif SDL_Rect dimensions; SDL_GetDisplayBounds(m_handle, &dimensions); m_pos_size = SDL_Rect_to_osd_rect(dimensions); m_usuable_pos_size = SDL_Rect_to_osd_rect(dimensions); m_is_primary = (m_handle == 0); #else #if defined(SDLMAME_WIN32) // Win32 version MONITORINFOEX info; info.cbSize = sizeof(info); GetMonitorInfo((HMONITOR)m_handle, (LPMONITORINFO)&info); m_pos_size = RECT_to_osd_rect(info.rcMonitor); m_usuable_pos_size = RECT_to_osd_rect(info.rcWork); m_is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) != 0); char *temp = utf8_from_wstring(info.szDevice); strncpy(m_name, temp, ARRAY_LENGTH(m_name) - 1); osd_free(temp); #elif defined(SDLMAME_MACOSX) // Mac OS X Core Imaging version CGDirectDisplayID primary; CGRect dbounds; // get the main display primary = CGMainDisplayID(); dbounds = CGDisplayBounds(primary); m_is_primary = (m_handle == 0); m_pos_size = osd_rect(0, 0, dbounds.size.width - dbounds.origin.x, dbounds.size.height - dbounds.origin.y); m_usuable_pos_size = m_pos_size; strncpy(m_name, "Mac OS X display", ARRAY_LENGTH(m_name) - 1); #elif defined(SDLMAME_X11) || defined(SDLMAME_NO_X11) // X11 version { #if defined(SDLMAME_X11) // X11 version int screen; SDL_SysWMinfo info; SDL_VERSION(&info.version); if ( SDL_GetWMInfo(&info) && (info.subsystem == SDL_SYSWM_X11) ) { screen = DefaultScreen(info.info.x11.display); SDL_VideoDriverName(m_name, ARRAY_LENGTH(m_name) - 1); m_pos_size = osd_rect(0, 0, DisplayWidth(info.info.x11.display, screen), DisplayHeight(info.info.x11.display, screen)); /* FIXME: If Xinerame is used we should compile a list of monitors * like we do for other targets and ignore SDL. */ if ((XineramaIsActive(info.info.x11.display)) && video_config.restrictonemonitor) { XineramaScreenInfo *xineinfo; int numscreens; xineinfo = XineramaQueryScreens(info.info.x11.display, &numscreens); m_pos_size = osd_rect(0, 0, xineinfo[0].width, xineinfo[0].height); XFree(xineinfo); } m_usuable_pos_size = m_pos_size; m_is_primary = (m_handle == 0); } else #endif // defined(SDLMAME_X11) { static int first_call=0; static int cw = 0, ch = 0; SDL_VideoDriverName(m_name, ARRAY_LENGTH(m_name) - 1); if (first_call==0) { const char *dimstr = osd_getenv(SDLENV_DESKTOPDIM); const SDL_VideoInfo *sdl_vi; sdl_vi = SDL_GetVideoInfo(); #if (SDL_VERSION_ATLEAST(1,2,10)) cw = sdl_vi->current_w; ch = sdl_vi->current_h; #endif first_call=1; if ((cw==0) || (ch==0)) { if (dimstr != NULL) { sscanf(dimstr, "%dx%d", &cw, &ch); } if ((cw==0) || (ch==0)) { osd_printf_warning("WARNING: SDL_GetVideoInfo() for driver <%s> is broken.\n", m_name); osd_printf_warning(" You should set SDLMAME_DESKTOPDIM to your desktop size.\n"); osd_printf_warning(" e.g. export SDLMAME_DESKTOPDIM=800x600\n"); osd_printf_warning(" Assuming 1024x768 now!\n"); cw=1024; ch=768; } } } m_pos_size = osd_rect(0, 0, cw, ch); m_usuable_pos_size = m_pos_size; m_is_primary = (m_handle == 0); } } #elif defined(SDLMAME_OS2) // OS2 version m_pos_size = osd_rect(0, 0, WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ), WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) ); m_usuable_pos_size = m_pos_size; m_is_primary = (m_handle == 0); strncpy(m_name, "OS/2 display", ARRAY_LENGTH(m_name) - 1); #else #error Unknown SDLMAME_xx OS type! #endif { static int info_shown=0; if (!info_shown) { osd_printf_verbose("SDL Device Driver : %s\n", m_name); osd_printf_verbose("SDL Monitor Dimensions: %d x %d\n", m_pos_size.width(), m_pos_size.height()); info_shown = 1; } } #endif // (SDLMAME_SDL2) }
void cheat_manager::load_cheats(const char *filename) { xml_data_node *rootnode = nullptr; std::string searchstr(machine().options().cheat_path()); path_iterator path(searchstr.c_str()); std::string curpath; while (path.next(curpath)) { searchstr.append(";").append(curpath).append(PATH_SEPARATOR).append("cheat"); } emu_file cheatfile(searchstr.c_str(), OPEN_FLAG_READ); try { // open the file with the proper name osd_file::error filerr = cheatfile.open(filename, ".xml"); // loop over all instrances of the files found in our search paths while (filerr == osd_file::error::NONE) { osd_printf_verbose("Loading cheats file from %s\n", cheatfile.fullpath()); // read the XML file into internal data structures xml_parse_options options = { nullptr }; xml_parse_error error; options.error = &error; rootnode = xml_file_read(cheatfile, &options); // if unable to parse the file, just bail if (rootnode == nullptr) throw emu_fatalerror("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message); // find the layout node xml_data_node *mamecheatnode = xml_get_sibling(rootnode->child, "mamecheat"); if (mamecheatnode == nullptr) throw emu_fatalerror("%s.xml: missing mamecheatnode node", filename); // validate the config data version int version = xml_get_attribute_int(mamecheatnode, "version", 0); if (version != CHEAT_VERSION) throw emu_fatalerror("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line); // parse all the elements for (xml_data_node *cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != nullptr; cheatnode = xml_get_sibling(cheatnode->next, "cheat")) { // load this entry auto curcheat = std::make_unique<cheat_entry>(*this, m_symtable, filename, *cheatnode); // make sure we're not a duplicate if (REMOVE_DUPLICATE_CHEATS && curcheat->is_duplicate()) { osd_printf_verbose("Ignoring duplicate cheat '%s' from file %s\n", curcheat->description(), cheatfile.fullpath()); } else // add to the end of the list m_cheatlist.push_back(std::move(curcheat)); } // free the file and loop for the next one xml_file_free(rootnode); // open the next file in sequence filerr = cheatfile.open_next(); } } // handle errors cleanly catch (emu_fatalerror &err) { osd_printf_error("%s\n", err.string()); m_cheatlist.clear(); if (rootnode != nullptr) xml_file_free(rootnode); } }
void renderer_dd::compute_blit_surface_size() { 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().m_hwnd, &client); // hardware stretch case: apply prescale if (video_config.hwstretch) { int prescale = (window().prescale() < 1) ? 1 : window().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) { osd_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); window().target()->compute_visible_area(target_width, target_height, monitor->aspect(), 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 != blitwidth || newheight != blitheight) { // force some updates update_outer_rects(); osd_printf_verbose("DirectDraw: New blit size = %dx%d\n", newwidth, newheight); } blitwidth = newwidth; blitheight = newheight; }
void renderer_dd::blit_to_primary(int srcwidth, int srcheight) { IDirectDrawSurface7 *target = (back != NULL) ? back : primary; osd_monitor_info *monitor = window().winwindow_video_window_monitor(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().m_hwnd, &outer); ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[0]); ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[1]); // adjust to be relative to the monitor osd_rect pos = monitor->position_size(); outer.left -= pos.left(); outer.right -= pos.left(); outer.top -= pos.top(); outer.bottom -= pos.top(); } // compute outer rect -- full screen version else { calc_fullscreen_margins(primarydesc.dwWidth, 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), monitor->aspect(), 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 != lastdest.left || dest.right != lastdest.right || dest.top != lastdest.top || dest.bottom != lastdest.bottom) { lastdest = dest; update_outer_rects(); } // clear outer rects if we need to if (clearouter != 0) { 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("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("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("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("DirectDraw: Error %08X clearing the screen\n", (int)result); } } // do the blit result = IDirectDrawSurface7_Blt(target, &dest, blit, &source, DDBLT_WAIT, NULL); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X blitting to the screen\n", (int)result); // page flip if triple buffered if (window().fullscreen() && back != NULL) { result = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); } }
int renderer_dd::ddraw_create_surfaces() { HRESULT result; // make a description of the primary surface memset(&primarydesc, 0, sizeof(primarydesc)); primarydesc.dwSize = sizeof(primarydesc); primarydesc.dwFlags = DDSD_CAPS; primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // for triple-buffered full screen mode, allocate flipping surfaces if (window().fullscreen() && video_config.triplebuf) { primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; primarydesc.dwBackBufferCount = 2; } // create the primary surface and report errors result = create_surface(&primarydesc, &primary, "primary"); if (result != DD_OK) goto error; // full screen mode: get the back surface back = NULL; if (window().fullscreen() && video_config.triplebuf) { DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; result = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &back); if (result != DD_OK) { osd_printf_verbose("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 (blitwidth == 0 || blitheight == 0) compute_blit_surface_size(); blitdesc = primarydesc; blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; blitdesc.dwWidth = blitwidth; blitdesc.dwHeight = blitheight; blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; // then create the blit surface, fall back to system memory if video mem doesn't work result = create_surface(&blitdesc, &blit, "blit"); if (result != DD_OK) { blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; result = create_surface(&blitdesc, &blit, "blit"); } if (result != DD_OK) goto error; // create a memory buffer for offscreen drawing if (membuffersize < blitwidth * blitheight * 4) { membuffersize = blitwidth * blitheight * 4; global_free_array(membuffer); membuffer = global_alloc_array_nothrow(UINT8, membuffersize); } if (membuffer == NULL) goto error; // create a clipper for windowed mode if (!window().fullscreen() && create_clipper()) 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 fgamma = options.full_screen_gamma(); if (brightness != 1.0f || contrast != 1.0f || fgamma != 1.0f) { // see if we can get a GammaControl object result = IDirectDrawSurface_QueryInterface(primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&gamma); if (result != DD_OK) { osd_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n"); this->gamma = NULL; } // proceed if we can if (this->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, fgamma) << 8; // attempt to set it result = IDirectDrawGammaControl_SetGammaRamp(this->gamma, 0, &ramp); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result); } } } // force some updates update_outer_rects(); return 0; error: ddraw_delete_surfaces(); return 1; }
int renderer_dd::draw(const int update) { render_primitive *prim; int usemembuffer = FALSE; HRESULT result; // if we're updating, remember to erase the outer stuff if (update) update_outer_rects(); // if we have a ddraw object, check the cooperative level if (ddraw_test_cooperative()) return 1; // get the size; if we're too small, delete the existing surfaces if (blitwidth > blitdesc.dwWidth || blitheight > blitdesc.dwHeight) ddraw_delete_surfaces(); // if we need to create surfaces, do it now if (blit == NULL && ddraw_create_surfaces() != 0) return 1; // select our surface and lock it result = IDirectDrawSurface7_Lock(blit, NULL, &blitdesc, DDLOCK_WAIT, NULL); if (result == DDERR_SURFACELOST) { osd_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n"); ddraw_delete_surfaces(); return 1; } if (result != DD_OK) { osd_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result); return 1; } // render to it window().m_primlist->acquire_lock(); // scan the list of primitives for tricky stuff for (prim = window().m_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 (blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; default: osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); break; } // handle copying to both 16bpp and 32bpp destinations for (y = 0; y < blitheight; y++) { if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) { UINT32 *src = (UINT32 *)membuffer + y * blitwidth; UINT32 *dst = (UINT32 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); for (x = 0; x < blitwidth; x++) *dst++ = *src++; } else if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) { UINT16 *src = (UINT16 *)membuffer + y * blitwidth; UINT16 *dst = (UINT16 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); for (x = 0; x < blitwidth; x++) *dst++ = *src++; } } } // otherwise, draw directly else { // based on the target format, use one of our standard renderers switch (blitdesc.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; default: osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); break; } } window().m_primlist->release_lock(); // unlock and blit result = IDirectDrawSurface7_Unlock(blit, NULL); if (result != DD_OK) osd_printf_verbose("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() || back == NULL)) { result = IDirectDraw7_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKBEGIN, NULL); if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); } // complete the blitting blit_to_primary(blitwidth, blitheight); return 0; }
int renderer_dd::config_adapter_mode() { DDDEVICEIDENTIFIER2 identifier; HRESULT result; // choose the monitor number get_adapter_for_monitor(window().monitor()); // create a temporary DirectDraw object result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); if (result != DD_OK) { osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); return 1; } // get the identifier result = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0); if (result != DD_OK) { osd_printf_error("Error getting identifier for device\n"); return 1; } osd_printf_verbose("DirectDraw: Configuring device %s\n", identifier.szDescription); // get the current display mode memset(&origmode, 0, sizeof(origmode)); origmode.dwSize = sizeof(origmode); result = IDirectDraw7_GetDisplayMode(ddraw, &origmode); if (result != DD_OK) { osd_printf_verbose("DirectDraw: Error %08X getting current display mode\n", (int)result); IDirectDraw7_Release(ddraw); return 1; } // choose a resolution: full screen mode case if (window().fullscreen()) { // default to the current mode exactly width = origmode.dwWidth; height = origmode.dwHeight; refresh = origmode.dwRefreshRate; // if we're allowed to switch resolutions, override with something better if (video_config.switchres) pick_best_mode(); } // release the DirectDraw object IDirectDraw7_Release(ddraw); ddraw = NULL; // if we're not changing resolutions, make sure we have a resolution we can handle if (!window().fullscreen() || !video_config.switchres) { switch (origmode.ddpfPixelFormat.dwRBitMask) { case 0x00ff0000: case 0x000000ff: case 0xf800: case 0x7c00: break; default: osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)origmode.ddpfPixelFormat.dwRBitMask, (int)origmode.ddpfPixelFormat.dwGBitMask, (int)origmode.ddpfPixelFormat.dwBBitMask); return 1; } } return 0; }
void menu_file_selector::populate(float &customtop, float &custombottom) { const file_selector_entry *selected_entry = nullptr; // clear out the menu entries m_entrylist.clear(); // open the directory util::zippath_directory::ptr directory; osd_file::error const err = util::zippath_directory::open(m_current_directory, directory); // add the "[empty slot]" entry if available if (m_has_empty) append_entry(SELECTOR_ENTRY_TYPE_EMPTY, "", ""); // add the "[create]" entry if (m_has_create && !directory->is_archive()) append_entry(SELECTOR_ENTRY_TYPE_CREATE, "", ""); // add and select the "[software list]" entry if available if (m_has_softlist) selected_entry = &append_entry(SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, "", ""); // add the drives int i = 0; for (char const *volume_name = osd_get_volume_name(i); volume_name; volume_name = osd_get_volume_name(++i)) append_entry(SELECTOR_ENTRY_TYPE_DRIVE, volume_name, volume_name); // mark first filename entry std::size_t const first = m_entrylist.size() + 1; // build the menu for each item if (osd_file::error::NONE != err) { osd_printf_verbose("menu_file_selector::populate: error opening directory '%s' (%d)\n", m_current_directory.c_str(), int(err)); } else { for (osd::directory::entry const *dirent = directory->readdir(); dirent; dirent = directory->readdir()) { // append a dirent entry file_selector_entry const *entry = append_dirent_entry(dirent); if (entry) { // set the selected item to be the first non-parent directory or file if (!selected_entry && strcmp(dirent->name, "..")) selected_entry = entry; // do we have to select this file? if (!core_stricmp(m_current_file.c_str(), dirent->name)) selected_entry = entry; } } } directory.reset(); // sort the menu entries const std::collate<wchar_t> &coll = std::use_facet<std::collate<wchar_t>>(std::locale()); std::sort( m_entrylist.begin() + first, m_entrylist.end(), [&coll] (file_selector_entry const &x, file_selector_entry const &y) { std::wstring const xstr = wstring_from_utf8(x.basename); std::wstring const ystr = wstring_from_utf8(y.basename); return coll.compare(xstr.data(), xstr.data()+xstr.size(), ystr.data(), ystr.data()+ystr.size()) < 0; }); // append all of the menu entries for (file_selector_entry const &entry : m_entrylist) append_entry_menu_item(&entry); // set the selection (if we have one) if (selected_entry) set_selection((void *)selected_entry); // set up custom render proc customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; }
void s32comm_device::comm_tick_15612() { // m_shared[0] = node link status (5 = linking, 1 = online) // m_shared[1] = node mode (0 = relay, 1 = master, 2 = slave) // m_shared[2] = node id // m_shared[3] = node count // m_shared[4] = ready-to-send if (m_linkenable == 0x01) { int frameStart = 0x0010; int frameOffset = 0x0000; int frameSize = 0x00E0; int dataSize = frameSize + 1; int recv = 0; int idx = 0; bool isMaster = (m_shared[1] == 0x01); bool isSlave = (m_shared[1] == 0x02); bool isRelay = (m_shared[1] == 0x00); if (m_linkalive == 0x02) { // link failed... m_shared[0] = 0xff; return; } else if (m_linkalive == 0x00) { // link not yet established... m_shared[0] = 0x05; // check rx socket if (!m_line_rx) { osd_printf_verbose("S32COMM: listen on %s\n", m_localhost); uint64_t filesize; // unused osd_file::open(m_localhost, OPEN_FLAG_CREATE, m_line_rx, filesize); } // check tx socket if (!m_line_tx) { osd_printf_verbose("S32COMM: connect to %s\n", m_remotehost); uint64_t filesize; // unused osd_file::open(m_remotehost, 0, m_line_tx, filesize); } // if both sockets are there check ring if (m_line_rx && m_line_tx) { // try to read one message recv = read_frame(dataSize); while (recv > 0) { // check if message id idx = m_buffer0[0]; // 0xFF - link id if (idx == 0xff) { if (isMaster) { // master gets first id and starts next state m_linkid = 0x01; m_linkcount = m_buffer0[1]; m_linktimer = 0x00; } else if (isSlave || isRelay) { // slave gets own id if (isSlave) { m_buffer0[1]++; m_linkid = m_buffer0[1]; } // slave and relay forward message send_frame(dataSize); } } // 0xFE - link size else if (idx == 0xfe) { if (isSlave || isRelay) { m_linkcount = m_buffer0[1]; // slave and relay forward message send_frame(dataSize); } // consider it done osd_printf_verbose("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); m_linkalive = 0x01; // write to shared mem m_shared[0] = 0x01; m_shared[2] = m_linkid; m_shared[3] = m_linkcount; } if (m_linkalive == 0x00) recv = read_frame(dataSize); else recv = 0; } // if we are master and link is not yet established if (isMaster && (m_linkalive == 0x00)) { // send first packet if (m_linktimer == 0x01) { m_buffer0[0] = 0xFF; m_buffer0[1] = 0x01; send_frame(dataSize); } // send second packet else if (m_linktimer == 0x00) { m_buffer0[0] = 0xFE; m_buffer0[1] = m_linkcount; send_frame(dataSize); // consider it done osd_printf_verbose("S32COMM: link established - id %02x of %02x\n", m_linkid, m_linkcount); m_linkalive = 0x01; // write to shared mem m_shared[0] = 0x01; m_shared[2] = m_linkid; m_shared[3] = m_linkcount; } else if (m_linktimer > 0x01) { // decrease delay timer m_linktimer--; } } } } // update "ring buffer" if link established if (m_linkalive == 0x01) { do { // try to read a message recv = read_frame(dataSize); while (recv > 0) { // check if valid id idx = m_buffer0[0]; if (idx > 0 && idx <= m_linkcount) { // if not own message if (idx != m_linkid) { // save message to "ring buffer" frameOffset = frameStart + (idx * frameSize); for (int j = 0x00 ; j < frameSize ; j++) { m_shared[frameOffset + j] = m_buffer0[1 + j]; } // forward message to other nodes send_frame(dataSize); } } else { if (idx == 0xfc) { // 0xFC - VSYNC m_linktimer = 0x00; if (!isMaster) // forward message to other nodes send_frame(dataSize); } if (idx == 0xfd) { // 0xFD - master addional bytes if (!isMaster) { // save message to "ring buffer" frameOffset = 0x05; for (int j = 0x00 ; j < 0x0b ; j++) { m_shared[frameOffset + j] = m_buffer0[1 + j]; } // forward message to other nodes send_frame(dataSize); } } } // try to read another message recv = read_frame(dataSize); } } while (m_linktimer == 0x01); // enable wait for vsync m_linktimer = m_framesync; // update "ring buffer" if link established // live relay does not send data if (m_linkid != 0x00) { // check ready-to-send flag if (m_shared[4] != 0x00) { send_data(m_linkid, frameStart, frameSize, dataSize); // save message to "ring buffer" frameOffset = frameStart + (m_linkid * frameSize); for (int j = 0x00 ; j < frameSize ; j++) { m_shared[frameOffset + j] = m_buffer0[1 + j]; } } if (isMaster) { // master sends some additional status bytes // master sends additional status bytes send_data(0xfd, 0x05, 0x0b, dataSize); // send vsync m_buffer0[0] = 0xfc; m_buffer0[1] = 0x01; send_frame(dataSize); } } // clear 04 m_shared[4] = 0x00; } } }
bool sdl_osd_interface::window_init() { osd_printf_verbose("Enter sdlwindow_init\n"); // get the main thread ID before anything else main_threadid = SDL_ThreadID(); // otherwise, treat the window thread as the main thread //window_threadid = main_threadid; sdlwindow_thread_id(nullptr, 0); // initialize the drawers switch (video_config.mode) { case VIDEO_MODE_BGFX: renderer_bgfx::init(machine()); break; #if (USE_OPENGL) case VIDEO_MODE_OPENGL: renderer_ogl::init(machine()); break; #endif case VIDEO_MODE_SDL2ACCEL: renderer_sdl2::init(machine()); break; case VIDEO_MODE_SOFT: renderer_sdl1::init(machine()); break; } /* We may want to set a number of the hints SDL2 provides. * The code below will document which hints were set. */ const char * hints[] = { SDL_HINT_FRAMEBUFFER_ACCELERATION, SDL_HINT_RENDER_DRIVER, SDL_HINT_RENDER_OPENGL_SHADERS, SDL_HINT_RENDER_SCALE_QUALITY, SDL_HINT_RENDER_VSYNC, SDL_HINT_VIDEO_X11_XVIDMODE, SDL_HINT_VIDEO_X11_XINERAMA, SDL_HINT_VIDEO_X11_XRANDR, SDL_HINT_GRAB_KEYBOARD, SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_HINT_IDLE_TIMER_DISABLED, SDL_HINT_ORIENTATIONS, SDL_HINT_XINPUT_ENABLED, SDL_HINT_GAMECONTROLLERCONFIG, SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, SDL_HINT_ALLOW_TOPMOST, SDL_HINT_TIMER_RESOLUTION, #if SDL_VERSION_ATLEAST(2, 0, 2) SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_HINT_VIDEO_ALLOW_SCREENSAVER, SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, SDL_HINT_VIDEO_WIN_D3DCOMPILER, SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT, SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_HINT_MOUSE_RELATIVE_MODE_WARP, #endif #if SDL_VERSION_ATLEAST(2, 0, 3) SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_HINT_VIDEO_HIGHDPI_DISABLED, SDL_HINT_WINRT_PRIVACY_POLICY_URL, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL, SDL_HINT_WINRT_HANDLE_BACK_BUTTON, #endif nullptr }; osd_printf_verbose("\nHints:\n"); for (int i = 0; hints[i] != nullptr; i++) osd_printf_verbose("\t%-40s %s\n", hints[i], SDL_GetHint(hints[i])); // set up the window list osd_printf_verbose("Leave sdlwindow_init\n"); return true; }
static void defines_verbose(void) { osd_printf_verbose("Build version: %s\n", build_version); osd_printf_verbose("Build architecure: "); MACRO_VERBOSE(SDLMAME_ARCH); osd_printf_verbose("\n"); osd_printf_verbose("Build defines 1: "); MACRO_VERBOSE(SDLMAME_UNIX); MACRO_VERBOSE(SDLMAME_X11); MACRO_VERBOSE(SDLMAME_WIN32); MACRO_VERBOSE(SDLMAME_MACOSX); MACRO_VERBOSE(SDLMAME_DARWIN); MACRO_VERBOSE(SDLMAME_LINUX); MACRO_VERBOSE(SDLMAME_SOLARIS); MACRO_VERBOSE(SDLMAME_IRIX); MACRO_VERBOSE(SDLMAME_BSD); osd_printf_verbose("\n"); osd_printf_verbose("Build defines 1: "); MACRO_VERBOSE(LSB_FIRST); MACRO_VERBOSE(PTR64); MACRO_VERBOSE(MAME_NOASM); MACRO_VERBOSE(MAME_DEBUG); MACRO_VERBOSE(BIGENDIAN); MACRO_VERBOSE(CPP_COMPILE); MACRO_VERBOSE(SYNC_IMPLEMENTATION); osd_printf_verbose("\n"); osd_printf_verbose("SDL/OpenGL defines: "); osd_printf_verbose("SDL_COMPILEDVERSION=%d ", SDL_COMPILEDVERSION); MACRO_VERBOSE(USE_OPENGL); MACRO_VERBOSE(USE_DISPATCH_GL); osd_printf_verbose("\n"); osd_printf_verbose("Compiler defines A: "); MACRO_VERBOSE(__GNUC__); MACRO_VERBOSE(__GNUC_MINOR__); MACRO_VERBOSE(__GNUC_PATCHLEVEL__); MACRO_VERBOSE(__VERSION__); osd_printf_verbose("\n"); osd_printf_verbose("Compiler defines B: "); MACRO_VERBOSE(__amd64__); MACRO_VERBOSE(__x86_64__); MACRO_VERBOSE(__unix__); MACRO_VERBOSE(__i386__); MACRO_VERBOSE(__ppc__); MACRO_VERBOSE(__ppc64__); osd_printf_verbose("\n"); osd_printf_verbose("Compiler defines C: "); MACRO_VERBOSE(_FORTIFY_SOURCE); MACRO_VERBOSE(__USE_FORTIFY_LEVEL); osd_printf_verbose("\n"); }
base *drawd3d9_init(void) { bool post_available = true; // dynamically grab the create function from d3d9.dll HINSTANCE dllhandle = LoadLibrary(TEXT("d3d9.dll")); if (dllhandle == nullptr) { osd_printf_verbose("Direct3D: Unable to access d3d9.dll\n"); return nullptr; } // import the create function direct3dcreate9_ptr direct3dcreate9 = (direct3dcreate9_ptr)GetProcAddress(dllhandle, "Direct3DCreate9"); if (direct3dcreate9 == nullptr) { osd_printf_verbose("Direct3D: Unable to find Direct3DCreate9\n"); FreeLibrary(dllhandle); return nullptr; } // create our core direct 3d object IDirect3D9 *d3d9 = (*direct3dcreate9)(D3D_SDK_VERSION); if (d3d9 == nullptr) { osd_printf_verbose("Direct3D: Error attempting to initialize Direct3D9\n"); FreeLibrary(dllhandle); return nullptr; } // dynamically grab the shader load function from d3dx9.dll HINSTANCE fxhandle = nullptr; for (int idx = 99; idx >= 0; idx--) // a shameful moogle { #ifdef UNICODE wchar_t dllbuf[13]; wsprintf(dllbuf, TEXT("d3dx9_%d.dll"), idx); fxhandle = LoadLibrary(dllbuf); #else char dllbuf[13]; sprintf(dllbuf, "d3dx9_%d.dll", idx); fxhandle = LoadLibraryA(dllbuf); #endif if (fxhandle != nullptr) { break; } } if (fxhandle == nullptr) { osd_printf_verbose("Direct3D: Warning - Unable find any D3D9 DLLs; disabling post-effect rendering\n"); post_available = false; } // allocate an object to hold our data auto d3dptr = global_alloc(base); d3dptr->version = 9; d3dptr->d3dobj = d3d9; d3dptr->dllhandle = dllhandle; d3dptr->post_fx_available = post_available; d3dptr->libhandle = fxhandle; set_interfaces(d3dptr); osd_printf_verbose("Direct3D: Using Direct3D 9\n"); return d3dptr; }
static void osd_sdl_info(void) { int i, num = SDL_GetNumVideoDrivers(); osd_printf_verbose("Available videodrivers: "); for (i=0;i<num;i++) { const char *name = SDL_GetVideoDriver(i); osd_printf_verbose("%s ", name); } osd_printf_verbose("\n"); osd_printf_verbose("Current Videodriver: %s\n", SDL_GetCurrentVideoDriver()); num = SDL_GetNumVideoDisplays(); for (i=0;i<num;i++) { SDL_DisplayMode mode; int j; osd_printf_verbose("\tDisplay #%d\n", i); if (SDL_GetDesktopDisplayMode(i, &mode)) osd_printf_verbose("\t\tDesktop Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate); if (SDL_GetCurrentDisplayMode(i, &mode)) osd_printf_verbose("\t\tCurrent Display Mode: %dx%d-%d@%d\n", mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate); osd_printf_verbose("\t\tRenderdrivers:\n"); for (j=0; j<SDL_GetNumRenderDrivers(); j++) { SDL_RendererInfo info; SDL_GetRenderDriverInfo(j, &info); osd_printf_verbose("\t\t\t%10s (%dx%d)\n", info.name, info.max_texture_width, info.max_texture_height); } } osd_printf_verbose("Available audio drivers: \n"); num = SDL_GetNumAudioDrivers(); for (i=0;i<num;i++) { osd_printf_verbose("\t%-20s\n", SDL_GetAudioDriver(i)); } }
//------------------------------------------------- // initialize command.dat index //------------------------------------------------- void datfile_manager::init_command() { int swcount = 0; int count = index_datafile(m_cmdidx, swcount); osd_printf_verbose("Command.dat games found = %i\n", count); }
void sdl_osd_interface::init(running_machine &machine) { // call our parent osd_common_t::init(machine); const char *stemp; // determine if we are benchmarking, and adjust options appropriately int bench = options().bench(); std::string error_string; if (bench > 0) { options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM, error_string); options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM, error_string); assert(error_string.c_str()[0] == 0); } // Some driver options - must be before audio init! stemp = options().audio_driver(); if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_printf_verbose("Setting SDL audiodriver '%s' ...\n", stemp); osd_setenv(SDLENV_AUDIODRIVER, stemp, 1); } stemp = options().video_driver(); if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_printf_verbose("Setting SDL videodriver '%s' ...\n", stemp); osd_setenv(SDLENV_VIDEODRIVER, stemp, 1); } stemp = options().render_driver(); if (stemp != NULL) { if (strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", stemp); //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1); SDL_SetHint(SDL_HINT_RENDER_DRIVER, stemp); } else { #if defined(SDLMAME_WIN32) // OpenGL renderer has less issues with mode switching on windows osd_printf_verbose("Setting SDL renderdriver '%s' ...\n", "opengl"); //osd_setenv(SDLENV_RENDERDRIVER, stemp, 1); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); #endif } } /* Set the SDL environment variable for drivers wanting to load the * lib at startup. */ #if USE_OPENGL /* FIXME: move lib loading code from drawogl.c here */ stemp = options().gl_lib(); if (stemp != NULL && strcmp(stemp, OSDOPTVAL_AUTO) != 0) { osd_setenv("SDL_VIDEO_GL_DRIVER", stemp, 1); osd_printf_verbose("Setting SDL_VIDEO_GL_DRIVER = '%s' ...\n", stemp); } #endif /* get number of processors */ stemp = options().numprocessors(); osd_num_processors = 0; if (strcmp(stemp, "auto") != 0) { osd_num_processors = atoi(stemp); if (osd_num_processors < 1) { osd_printf_warning("numprocessors < 1 doesn't make much sense. Assuming auto ...\n"); osd_num_processors = 0; } } /* Initialize SDL */ if (!SDLMAME_INIT_IN_WORKER_THREAD) { #ifdef SDLMAME_EMSCRIPTEN // timer brings in threads which are not supported in Emscripten if (SDL_InitSubSystem(SDL_INIT_VIDEO| SDL_INIT_GAMECONTROLLER|SDL_INIT_NOPARACHUTE)) { #else if (SDL_InitSubSystem(SDL_INIT_TIMER| SDL_INIT_VIDEO| SDL_INIT_GAMECONTROLLER|SDL_INIT_NOPARACHUTE)) { #endif osd_printf_error("Could not initialize SDL %s\n", SDL_GetError()); exit(-1); } osd_sdl_info(); } defines_verbose(); osd_common_t::init_subsystems(); if (options().oslog()) machine.add_logerror_callback(output_oslog); /* now setup watchdog */ int watchdog_timeout = options().watchdog(); if (watchdog_timeout != 0) { m_watchdog = auto_alloc(machine, watchdog); m_watchdog->setTimeout(watchdog_timeout); } #ifdef SDLMAME_EMSCRIPTEN SDL_EventState(SDL_TEXTINPUT, SDL_FALSE); #else SDL_EventState(SDL_TEXTINPUT, SDL_TRUE); #endif }
osd_dim sdl_window_info::pick_best_mode() { int minimum_width, minimum_height, target_width, target_height; int i; int num; float size_score, best_score = 0.0f; osd_dim ret(0,0); // determine the minimum width/height for the selected target m_target->compute_minimum_size(minimum_width, minimum_height); // use those as the target for now target_width = minimum_width * MAX(1, prescale()); target_height = minimum_height * MAX(1, prescale()); // if we're not stretching, allow some slop on the minimum since we can handle it { minimum_width -= 4; minimum_height -= 4; } // FIXME: this should be provided by monitor ! num = SDL_GetNumDisplayModes(*((UINT64 *)m_monitor->oshandle())); if (num == 0) { osd_printf_error("SDL: No modes available?!\n"); exit(-1); } else { for (i = 0; i < num; ++i) { SDL_DisplayMode mode; SDL_GetDisplayMode(*((UINT64 *)m_monitor->oshandle()), i, &mode); // compute initial score based on difference between target and current size_score = 1.0f / (1.0f + abs((INT32)mode.w - target_width) + abs((INT32)mode.h - target_height)); // if the mode is too small, give a big penalty if (mode.w < minimum_width || mode.h < minimum_height) size_score *= 0.01f; // if mode is smaller than we'd like, it only scores up to 0.1 if (mode.w < target_width || mode.h < target_height) size_score *= 0.1f; // if we're looking for a particular mode, that's a winner if (mode.w == m_win_config.width && mode.h == m_win_config.height) size_score = 2.0f; // refresh adds some points if (m_win_config.refresh) size_score *= 1.0f / (1.0f + abs(m_win_config.refresh - mode.refresh_rate) / 10.0f); osd_printf_verbose("%4dx%4d@%2d -> %f\n", (int)mode.w, (int)mode.h, (int) mode.refresh_rate, (double) size_score); // best so far? if (size_score > best_score) { best_score = size_score; ret = osd_dim(mode.w, mode.h); } } } return ret; }
chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) { chd_error state = CHDERR_NONE; uint8_t sector_content[16384]; int sectorcount = m_param.sectors_per_track; int size = m_param.sector_size; int position = 0; // will be incremented by each encode call int sec_number = 0; int identfield = 0; int cylfield = 0; int headfield = 0; int sizefield = (size >> 7)-1; // If we don't have interleave data in the CHD, take a default if (m_param.interleave==0) { m_param.interleave = get_default(MFMHD_IL); m_param.cylskew = get_default(MFMHD_CSKEW); m_param.headskew = get_default(MFMHD_HSKEW); } int sec_il_start = (m_param.cylskew * cylinder + m_param.headskew * head) % sectorcount; int delta = (sectorcount + m_param.interleave-1) / m_param.interleave; if (TRACE_RWTRACK) osd_printf_verbose("%s: Load track (c=%d,h=%d) from CHD, interleave=%d, cylskew=%d, headskew=%d\n", tag(), cylinder, head, m_param.interleave, m_param.cylskew, m_param.headskew); m_lastbit = false; if (m_param.sync==0) { m_param.gap1 = get_default(MFMHD_GAP1); m_param.gap2 = get_default(MFMHD_GAP2); m_param.gap3 = get_default(MFMHD_GAP3); m_param.sync = get_default(MFMHD_SYNC); m_param.headerlen = get_default(MFMHD_HLEN); m_param.ecctype = get_default(MFMHD_ECC); } // Gap 1 mfm_encode(trackimage, position, 0x4e, m_param.gap1); if (TRACE_LAYOUT) osd_printf_verbose("%s: cyl=%d head=%d: sector sequence = ", tag(), cylinder, head); sec_number = sec_il_start; for (int sector = 0; sector < sectorcount; sector++) { if (TRACE_LAYOUT) osd_printf_verbose("%02d ", sec_number); // Sync gap mfm_encode(trackimage, position, 0x00, m_param.sync); // Write IDAM mfm_encode_a1(trackimage, position); // Write header identfield = cylinder_to_ident(cylinder); cylfield = cylinder & 0xff; headfield = head & 0x0f; if (m_param.headerlen==5) headfield |= ((cylinder & 0x700)>>4); mfm_encode(trackimage, position, identfield); mfm_encode(trackimage, position, cylfield); mfm_encode(trackimage, position, headfield); mfm_encode(trackimage, position, sec_number); if (m_param.headerlen==5) mfm_encode(trackimage, position, sizefield); // Write CRC for header. int crc = m_current_crc; mfm_encode(trackimage, position, (crc >> 8) & 0xff); mfm_encode(trackimage, position, crc & 0xff); // Gap 2 mfm_encode(trackimage, position, 0x4e, m_param.gap2); // Sync mfm_encode(trackimage, position, 0x00, m_param.sync); // Write DAM mfm_encode_a1(trackimage, position); mfm_encode(trackimage, position, 0xfb); // Get sector content from CHD int lbaposition = chs_to_lba(cylinder, head, sec_number); if (lbaposition>=0) { chd_error state = chdfile->read_units(lbaposition, sector_content); if (state != CHDERR_NONE) break; } else { osd_printf_verbose("%s: Invalid CHS data (%d,%d,%d); not loading from CHD\n", tag(), cylinder, head, sector); } for (int i=0; i < size; i++) mfm_encode(trackimage, position, sector_content[i]); // Write CRC for content. crc = m_current_crc; mfm_encode(trackimage, position, (crc >> 8) & 0xff); mfm_encode(trackimage, position, crc & 0xff); // Gap 3 mfm_encode(trackimage, position, 0x00, 3); mfm_encode(trackimage, position, 0x4e, m_param.gap3-3); // Calculate next sector number sec_number += delta; if (sec_number >= sectorcount) { sec_il_start = (sec_il_start+1) % delta; sec_number = sec_il_start; } } if (TRACE_LAYOUT) osd_printf_verbose("\n"); // Gap 4 if (state == CHDERR_NONE) { // Fill the rest with 0x4e mfm_encode(trackimage, position, 0x4e, tracksize-position); if (TRACE_IMAGE) showtrack(trackimage, tracksize); } return state; }