mirror of
https://github.com/holub/mame
synced 2025-06-10 14:52:42 +03:00

loader rewrite, which is still in progress....) Replaced mamedriv.c with a new driver list mechanism that is generated by the build tools. The emulator core now expects the presence of a file called src/$(TARGET)/$(SUBTARGET).lst which is just a raw list of driver names, one per line. C and C++ comments are still permitted. This file is parsed by a new build tool makelist which extracts the driver names, sorts them, and generates a file called drivlist.c, which is consumed by the core. [Aaron Giles] Added new osdcore function osd_malloc_array() which is identical to osd_malloc() but obviously hints that the underlying allocation is for an array. Updated all callers to use the appropriate form. Modified the Windows allocator to only use guard pages for array-style allocations, allowing us to enable them once again in debug builds. [Aaron Giles] Created new static class driver_list to wrap accesses to the list of available drivers. Improved speed of driver lookups by relying on the presorting done by makelist. [Aaron Giles] Created helper class driver_enumerator as a helper for iterating through the list of drivers. This class supports basic filtering and iteration, and also serves as a temporary cache of machine_configs. [Aaron Giles] Created cli_frontend object to wrap all the CLI handling code in clifront.c. Updated/simplified all the code to take advantage of the driver_enumerator. [Aaron Giles] Created media_auditor object to wrap all the auditing functions in audit.c. Updated all users to the new interface. Note that the new auditing mechanism is slightly out of sync with the romload code in terms of finding ROMs owned by devices, so it may mis-report some issues until the new ROM loading code is in. [Aaron Giles] Added concept of a per-device searchpath. For most devices, their searchpath is just the short name of the device. For driver_devices, the searchpath is driver[;parent[;bios]]. This searchpath will eventually be used by the rom loader to find ROMs. For now it is used by the media auditor only. [Aaron Giles] Created info_xml_creator object to wrap all the info generation functions in info.c. Converted the file to C++ and cleaned up the input processing code. [Aaron Giles] (not for whatsnew ... Known issues: auditing of CHDs appears busted, and debug builds report unfreed memory if you use the built-in game picker)
399 lines
9.6 KiB
C
399 lines
9.6 KiB
C
//============================================================
|
|
//
|
|
// sdlos_*.c - OS specific low level code
|
|
//
|
|
// Copyright (c) 1996-2010, Nicola Salmoria and the MAME Team.
|
|
// Visit http://mamedev.org for licensing and usage restrictions.
|
|
//
|
|
// SDLMAME by Olivier Galibert and R. Belmont
|
|
//
|
|
//============================================================
|
|
|
|
// standard sdl header
|
|
#include <SDL/SDL.h>
|
|
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include <mach/mach.h>
|
|
#include <mach/mach_time.h>
|
|
#include <Carbon/Carbon.h>
|
|
|
|
// MAME headers
|
|
#include "osdcore.h"
|
|
|
|
//============================================================
|
|
// PROTOTYPES
|
|
//============================================================
|
|
|
|
static osd_ticks_t init_cycle_counter(void);
|
|
static osd_ticks_t mach_cycle_counter(void);
|
|
|
|
//============================================================
|
|
// STATIC VARIABLES
|
|
//============================================================
|
|
|
|
static osd_ticks_t (*cycle_counter)(void) = init_cycle_counter;
|
|
static osd_ticks_t (*ticks_counter)(void) = init_cycle_counter;
|
|
static osd_ticks_t ticks_per_second;
|
|
|
|
//============================================================
|
|
// init_cycle_counter
|
|
//
|
|
// to avoid total grossness, this function is split by subarch
|
|
//============================================================
|
|
|
|
static osd_ticks_t init_cycle_counter(void)
|
|
{
|
|
osd_ticks_t start, end;
|
|
osd_ticks_t a, b;
|
|
|
|
cycle_counter = mach_cycle_counter;
|
|
ticks_counter = mach_cycle_counter;
|
|
|
|
// wait for an edge on the timeGetTime call
|
|
a = SDL_GetTicks();
|
|
do
|
|
{
|
|
b = SDL_GetTicks();
|
|
} while (a == b);
|
|
|
|
// get the starting cycle count
|
|
start = (*cycle_counter)();
|
|
|
|
// now wait for 1/4 second total
|
|
do
|
|
{
|
|
a = SDL_GetTicks();
|
|
} while (a - b < 250);
|
|
|
|
// get the ending cycle count
|
|
end = (*cycle_counter)();
|
|
|
|
// compute ticks_per_sec
|
|
ticks_per_second = (end - start) * 4;
|
|
|
|
// return the current cycle count
|
|
return (*cycle_counter)();
|
|
}
|
|
|
|
//============================================================
|
|
// performance_cycle_counter
|
|
//============================================================
|
|
|
|
//============================================================
|
|
// mach_cycle_counter
|
|
//============================================================
|
|
static osd_ticks_t mach_cycle_counter(void)
|
|
{
|
|
return mach_absolute_time();
|
|
}
|
|
|
|
//============================================================
|
|
// osd_cycles
|
|
//============================================================
|
|
|
|
osd_ticks_t osd_ticks(void)
|
|
{
|
|
return (*cycle_counter)();
|
|
}
|
|
|
|
|
|
//============================================================
|
|
// osd_ticks_per_second
|
|
//============================================================
|
|
|
|
osd_ticks_t osd_ticks_per_second(void)
|
|
{
|
|
if (ticks_per_second == 0)
|
|
{
|
|
return 1; // this isn't correct, but it prevents the crash
|
|
}
|
|
return ticks_per_second;
|
|
}
|
|
|
|
|
|
|
|
//============================================================
|
|
// osd_sleep
|
|
//============================================================
|
|
|
|
void osd_sleep(osd_ticks_t duration)
|
|
{
|
|
UINT32 msec;
|
|
|
|
// make sure we've computed ticks_per_second
|
|
if (ticks_per_second == 0)
|
|
(void)osd_ticks();
|
|
|
|
// convert to milliseconds, rounding down
|
|
msec = (UINT32)(duration * 1000 / ticks_per_second);
|
|
|
|
// only sleep if at least 2 full milliseconds
|
|
if (msec >= 2)
|
|
{
|
|
// take a couple of msecs off the top for good measure
|
|
msec -= 2;
|
|
usleep(msec*1000);
|
|
}
|
|
}
|
|
|
|
//============================================================
|
|
// osd_num_processors
|
|
//============================================================
|
|
|
|
int osd_num_processors(void)
|
|
{
|
|
int processors = 1;
|
|
|
|
struct host_basic_info host_basic_info;
|
|
unsigned int count;
|
|
kern_return_t r;
|
|
mach_port_t my_mach_host_self;
|
|
|
|
count = HOST_BASIC_INFO_COUNT;
|
|
my_mach_host_self = mach_host_self();
|
|
if ( ( r = host_info(my_mach_host_self, HOST_BASIC_INFO, (host_info_t)(&host_basic_info), &count)) == KERN_SUCCESS )
|
|
{
|
|
processors = host_basic_info.avail_cpus;
|
|
}
|
|
mach_port_deallocate(mach_task_self(), my_mach_host_self);
|
|
|
|
return processors;
|
|
}
|
|
|
|
//============================================================
|
|
// osd_malloc
|
|
//============================================================
|
|
|
|
void *osd_malloc(size_t size)
|
|
{
|
|
#ifndef MALLOC_DEBUG
|
|
return malloc(size);
|
|
#else
|
|
#error "MALLOC_DEBUG not yet supported"
|
|
#endif
|
|
}
|
|
|
|
|
|
//============================================================
|
|
// osd_malloc_array
|
|
//============================================================
|
|
|
|
void *osd_malloc_array(size_t size)
|
|
{
|
|
#ifndef MALLOC_DEBUG
|
|
return malloc(size);
|
|
#else
|
|
#error "MALLOC_DEBUG not yet supported"
|
|
#endif
|
|
}
|
|
|
|
|
|
//============================================================
|
|
// osd_free
|
|
//============================================================
|
|
|
|
void osd_free(void *ptr)
|
|
{
|
|
#ifndef MALLOC_DEBUG
|
|
free(ptr);
|
|
#else
|
|
#error "MALLOC_DEBUG not yet supported"
|
|
#endif
|
|
}
|
|
|
|
//============================================================
|
|
// osd_getenv
|
|
//============================================================
|
|
|
|
char *osd_getenv(const char *name)
|
|
{
|
|
return getenv(name);
|
|
}
|
|
|
|
//============================================================
|
|
// osd_setenv
|
|
//============================================================
|
|
|
|
int osd_setenv(const char *name, const char *value, int overwrite)
|
|
{
|
|
return setenv(name, value, overwrite);
|
|
}
|
|
|
|
//============================================================
|
|
// osd_get_clipboard_text
|
|
//============================================================
|
|
|
|
char *osd_get_clipboard_text(void)
|
|
{
|
|
char *result = NULL; /* core expects a malloced C string of uft8 data */
|
|
|
|
PasteboardRef pasteboard_ref;
|
|
OSStatus err;
|
|
PasteboardSyncFlags sync_flags;
|
|
PasteboardItemID item_id;
|
|
CFIndex flavor_count;
|
|
CFArrayRef flavor_type_array;
|
|
CFIndex flavor_index;
|
|
ItemCount item_count;
|
|
UInt32 item_index;
|
|
Boolean success = false;
|
|
|
|
err = PasteboardCreate(kPasteboardClipboard, &pasteboard_ref);
|
|
|
|
if (!err)
|
|
{
|
|
sync_flags = PasteboardSynchronize( pasteboard_ref );
|
|
|
|
err = PasteboardGetItemCount(pasteboard_ref, &item_count );
|
|
|
|
for (item_index=1; item_index<=item_count; item_index++)
|
|
{
|
|
err = PasteboardGetItemIdentifier(pasteboard_ref, item_index, &item_id);
|
|
|
|
if (!err)
|
|
{
|
|
err = PasteboardCopyItemFlavors(pasteboard_ref, item_id, &flavor_type_array);
|
|
|
|
if (!err)
|
|
{
|
|
flavor_count = CFArrayGetCount(flavor_type_array);
|
|
|
|
for (flavor_index = 0; flavor_index < flavor_count; flavor_index++)
|
|
{
|
|
CFStringRef flavor_type;
|
|
CFDataRef flavor_data;
|
|
CFStringEncoding encoding;
|
|
CFStringRef string_ref;
|
|
CFDataRef data_ref;
|
|
CFIndex length;
|
|
CFRange range;
|
|
|
|
flavor_type = (CFStringRef)CFArrayGetValueAtIndex(flavor_type_array, flavor_index);
|
|
|
|
if (UTTypeConformsTo (flavor_type, kUTTypeUTF16PlainText))
|
|
encoding = kCFStringEncodingUTF16;
|
|
else if (UTTypeConformsTo (flavor_type, kUTTypeUTF8PlainText))
|
|
encoding = kCFStringEncodingUTF8;
|
|
else if (UTTypeConformsTo (flavor_type, kUTTypePlainText))
|
|
encoding = kCFStringEncodingMacRoman;
|
|
else
|
|
continue;
|
|
|
|
err = PasteboardCopyItemFlavorData(pasteboard_ref, item_id, flavor_type, &flavor_data);
|
|
|
|
if( !err )
|
|
{
|
|
string_ref = CFStringCreateFromExternalRepresentation (kCFAllocatorDefault, flavor_data, encoding);
|
|
data_ref = CFStringCreateExternalRepresentation (kCFAllocatorDefault, string_ref, kCFStringEncodingUTF8, '?');
|
|
|
|
length = CFDataGetLength (data_ref);
|
|
range = CFRangeMake (0,length);
|
|
|
|
result = (char *)osd_malloc_array (length+1);
|
|
if (result != NULL)
|
|
{
|
|
CFDataGetBytes (data_ref, range, (unsigned char *)result);
|
|
result[length] = 0;
|
|
success = true;
|
|
break;
|
|
}
|
|
|
|
CFRelease(data_ref);
|
|
CFRelease(string_ref);
|
|
CFRelease(flavor_data);
|
|
}
|
|
}
|
|
|
|
CFRelease(flavor_type_array);
|
|
}
|
|
}
|
|
|
|
if (success)
|
|
break;
|
|
}
|
|
|
|
CFRelease(pasteboard_ref);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//============================================================
|
|
// osd_stat
|
|
//============================================================
|
|
|
|
osd_directory_entry *osd_stat(const char *path)
|
|
{
|
|
int err;
|
|
osd_directory_entry *result = NULL;
|
|
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_NO64BITIO)
|
|
struct stat st;
|
|
#else
|
|
struct stat64 st;
|
|
#endif
|
|
|
|
#if defined(SDLMAME_DARWIN) || defined(SDLMAME_NO64BITIO)
|
|
err = stat(path, &st);
|
|
#else
|
|
err = stat64(path, &st);
|
|
#endif
|
|
|
|
if( err == -1) return NULL;
|
|
|
|
// create an osd_directory_entry; be sure to make sure that the caller can
|
|
// free all resources by just freeing the resulting osd_directory_entry
|
|
result = (osd_directory_entry *) osd_malloc_array(sizeof(*result) + strlen(path) + 1);
|
|
strcpy(((char *) result) + sizeof(*result), path);
|
|
result->name = ((char *) result) + sizeof(*result);
|
|
result->type = S_ISDIR(st.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE;
|
|
result->size = (UINT64)st.st_size;
|
|
|
|
return result;
|
|
}
|
|
|
|
//============================================================
|
|
// osd_get_volume_name
|
|
//============================================================
|
|
|
|
const char *osd_get_volume_name(int idx)
|
|
{
|
|
if (idx!=0) return NULL;
|
|
return "/";
|
|
}
|
|
|
|
//============================================================
|
|
// osd_get_full_path
|
|
//============================================================
|
|
|
|
file_error osd_get_full_path(char **dst, const char *path)
|
|
{
|
|
file_error err;
|
|
char path_buffer[512];
|
|
|
|
err = FILERR_NONE;
|
|
|
|
if (getcwd(path_buffer, 511) == NULL)
|
|
{
|
|
printf("osd_get_full_path: failed!\n");
|
|
err = FILERR_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
*dst = (char *)osd_malloc_array(strlen(path_buffer)+strlen(path)+3);
|
|
|
|
// if it's already a full path, just pass it through
|
|
if (path[0] == '/')
|
|
{
|
|
strcpy(*dst, path);
|
|
}
|
|
else
|
|
{
|
|
sprintf(*dst, "%s%s%s", path_buffer, PATH_SEPARATOR, path);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|