diff options
Diffstat (limited to 'src/osd')
-rw-r--r-- | src/osd/osdcore.h | 22 | ||||
-rw-r--r-- | src/osd/osdmini/minimain.c | 10 | ||||
-rw-r--r-- | src/osd/osdmini/minimisc.c | 12 | ||||
-rw-r--r-- | src/osd/sdl/draw13.c | 2 | ||||
-rw-r--r-- | src/osd/sdl/sdldir.c | 8 | ||||
-rw-r--r-- | src/osd/sdl/sdlfile.c | 8 | ||||
-rw-r--r-- | src/osd/sdl/sdlmain.c | 3 | ||||
-rw-r--r-- | src/osd/sdl/sdlos_macosx.c | 20 | ||||
-rw-r--r-- | src/osd/sdl/sdlos_os2.c | 18 | ||||
-rw-r--r-- | src/osd/sdl/sdlos_unix.c | 20 | ||||
-rw-r--r-- | src/osd/sdl/sdlos_win32.c | 71 | ||||
-rw-r--r-- | src/osd/sdl/sdlwork.c | 2 | ||||
-rw-r--r-- | src/osd/sdl/strconv.c | 4 | ||||
-rw-r--r-- | src/osd/windows/strconv.c | 8 | ||||
-rw-r--r-- | src/osd/windows/winalloc.c | 618 | ||||
-rw-r--r-- | src/osd/windows/winmain.c | 3 | ||||
-rw-r--r-- | src/osd/windows/winmisc.c | 70 |
17 files changed, 190 insertions, 709 deletions
diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h index 6f98828f4b3..b4d22bc3bfc 100644 --- a/src/osd/osdcore.h +++ b/src/osd/osdcore.h @@ -723,7 +723,7 @@ void osd_work_item_release(osd_work_item *item); ***************************************************************************/ /*----------------------------------------------------------------------------- - osd_malloc: allocate memory that + osd_malloc: allocate memory Parameters: @@ -742,6 +742,26 @@ void *osd_malloc(size_t size); /*----------------------------------------------------------------------------- + osd_malloc_array: allocate memory, hinting tha this memory contains an + array + + Parameters: + + size - the number of bytes to allocate + + Return value: + + a pointer to the allocated memory + + Notes: + + This is just a hook to do OS-specific allocation trickery. + It can be safely written as a wrapper to malloc(). +-----------------------------------------------------------------------------*/ +void *osd_malloc_array(size_t size); + + +/*----------------------------------------------------------------------------- osd_free: free memory allocated by osd_malloc Parameters: diff --git a/src/osd/osdmini/minimain.c b/src/osd/osdmini/minimain.c index 69a3037bcb0..0e43ce3e0a6 100644 --- a/src/osd/osdmini/minimain.c +++ b/src/osd/osdmini/minimain.c @@ -93,10 +93,12 @@ static INT32 keyboard_get_state(void *device_internal, void *item_internal); int main(int argc, char *argv[]) { - // cli_execute does the heavy lifting; if we have osd-specific options, we - // would pass them as the third parameter here + // cli_frontend does the heavy lifting; if we have osd-specific options, we + // create a derivative of cli_options and add our own + cli_options options; mini_osd_interface osd; - return cli_execute(argc, argv, osd, NULL); + cli_frontend frontend(options, osd); + return frontend.execute(argc, argv); } @@ -135,7 +137,7 @@ void mini_osd_interface::init(running_machine &machine) // initialize the input system by adding devices // let's pretend like we have a keyboard device - keyboard_device = input_device_add(&machine, DEVICE_CLASS_KEYBOARD, "Keyboard", NULL); + keyboard_device = input_device_add(machine, DEVICE_CLASS_KEYBOARD, "Keyboard", NULL); if (keyboard_device == NULL) fatalerror("Error creating keyboard device"); diff --git a/src/osd/osdmini/minimisc.c b/src/osd/osdmini/minimisc.c index 8d040b28e0e..1a4c3a33da6 100644 --- a/src/osd/osdmini/minimisc.c +++ b/src/osd/osdmini/minimisc.c @@ -44,7 +44,7 @@ //============================================================ -// osd_alloc +// osd_malloc //============================================================ void *osd_malloc(size_t size) @@ -54,6 +54,16 @@ void *osd_malloc(size_t size) //============================================================ +// osd_malloc_array +//============================================================ + +void *osd_malloc_array(size_t size) +{ + return malloc(size); +} + + +//============================================================ // osd_free //============================================================ diff --git a/src/osd/sdl/draw13.c b/src/osd/sdl/draw13.c index aa20f9ca2a6..b30d3fc2fc4 100644 --- a/src/osd/sdl/draw13.c +++ b/src/osd/sdl/draw13.c @@ -964,7 +964,7 @@ static texture_info *texture_create(sdl_window_info *window, const render_texinf if ( (texture->copyinfo->func != NULL) && (texture->sdl_access == SDL_TEXTUREACCESS_STATIC)) { - texture->pixels = osd_malloc(texture->setup.rotwidth * texture->setup.rotheight * texture->copyinfo->dst_bpp); + texture->pixels = osd_malloc_array(texture->setup.rotwidth * texture->setup.rotheight * texture->copyinfo->dst_bpp); texture->pixels_own=TRUE; } /* add us to the texture list */ diff --git a/src/osd/sdl/sdldir.c b/src/osd/sdl/sdldir.c index d70f81eb07c..b27711f0338 100644 --- a/src/osd/sdl/sdldir.c +++ b/src/osd/sdl/sdldir.c @@ -67,7 +67,7 @@ struct _osd_directory static char *build_full_path(const char *path, const char *file) { - char *ret = (char *) osd_malloc(strlen(path)+strlen(file)+2); + char *ret = (char *) osd_malloc_array(strlen(path)+strlen(file)+2); char *p = ret; strcpy(p, path); @@ -126,13 +126,13 @@ osd_directory *osd_opendir(const char *dirname) dir->fd = NULL; } - tmpstr = (char *) osd_malloc(strlen(dirname)+1); + tmpstr = (char *) osd_malloc_array(strlen(dirname)+1); strcpy(tmpstr, dirname); if (tmpstr[0] == '$') { char *envval; - envstr = (char *) osd_malloc(strlen(tmpstr)+1); + envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); strcpy(envstr, tmpstr); @@ -149,7 +149,7 @@ osd_directory *osd_opendir(const char *dirname) { j = strlen(envval) + strlen(tmpstr) + 1; osd_free(tmpstr); - tmpstr = (char *) osd_malloc(j); + tmpstr = (char *) osd_malloc_array(j); // start with the value of $HOME strcpy(tmpstr, envval); diff --git a/src/osd/sdl/sdlfile.c b/src/osd/sdl/sdlfile.c index 3326c474746..d7fc70fce4b 100644 --- a/src/osd/sdl/sdlfile.c +++ b/src/osd/sdl/sdlfile.c @@ -115,7 +115,7 @@ file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 tmpstr = NULL; // allocate a file object, plus space for the converted filename - *file = (osd_file *) osd_malloc(sizeof(**file) + sizeof(char) * strlen(path)); + *file = (osd_file *) osd_malloc_array(sizeof(**file) + sizeof(char) * strlen(path)); if (*file == NULL) { filerr = FILERR_OUT_OF_MEMORY; @@ -160,14 +160,14 @@ file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 goto error; } - tmpstr = (char *) osd_malloc(strlen((*file)->filename)+1); + tmpstr = (char *) osd_malloc_array(strlen((*file)->filename)+1); strcpy(tmpstr, (*file)->filename); // does path start with an environment variable? if (tmpstr[0] == '$') { char *envval; - envstr = (char *) osd_malloc(strlen(tmpstr)+1); + envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); strcpy(envstr, tmpstr); @@ -184,7 +184,7 @@ file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 { j = strlen(envval) + strlen(tmpstr) + 1; osd_free(tmpstr); - tmpstr = (char *) osd_malloc(j); + tmpstr = (char *) osd_malloc_array(j); // start with the value of $HOME strcpy(tmpstr, envval); diff --git a/src/osd/sdl/sdlmain.c b/src/osd/sdl/sdlmain.c index 747b881d060..e54de5bcf6b 100644 --- a/src/osd/sdl/sdlmain.c +++ b/src/osd/sdl/sdlmain.c @@ -348,7 +348,8 @@ int main(int argc, char *argv[]) { sdl_osd_interface osd; sdl_options options; - res = cli_execute(options, osd, argc, argv); + cli_frontend frontend(options, osd); + res = frontend.execute(argc, argv); } #ifdef MALLOC_DEBUG diff --git a/src/osd/sdl/sdlos_macosx.c b/src/osd/sdl/sdlos_macosx.c index baa8ac2d167..c37eb8ad726 100644 --- a/src/osd/sdl/sdlos_macosx.c +++ b/src/osd/sdl/sdlos_macosx.c @@ -177,6 +177,20 @@ void *osd_malloc(size_t size) //============================================================ +// 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 //============================================================ @@ -277,7 +291,7 @@ char *osd_get_clipboard_text(void) length = CFDataGetLength (data_ref); range = CFRangeMake (0,length); - result = (char *)osd_malloc (length+1); + result = (char *)osd_malloc_array (length+1); if (result != NULL) { CFDataGetBytes (data_ref, range, (unsigned char *)result); @@ -330,7 +344,7 @@ osd_directory_entry *osd_stat(const char *path) // 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(sizeof(*result) + strlen(path) + 1); + 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; @@ -367,7 +381,7 @@ file_error osd_get_full_path(char **dst, const char *path) } else { - *dst = (char *)osd_malloc(strlen(path_buffer)+strlen(path)+3); + *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] == '/') diff --git a/src/osd/sdl/sdlos_os2.c b/src/osd/sdl/sdlos_os2.c index 97a0f8419ac..87512222db4 100644 --- a/src/osd/sdl/sdlos_os2.c +++ b/src/osd/sdl/sdlos_os2.c @@ -199,6 +199,20 @@ void *osd_malloc(size_t size) //============================================================ +// 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 //============================================================ @@ -258,7 +272,7 @@ osd_directory_entry *osd_stat(const char *path) // 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(sizeof(*result) + strlen(path) + result = (osd_directory_entry *) osd_malloc_array(sizeof(*result) + strlen(path) 1); strcpy(((char *) result) + sizeof(*result), path); result->name = ((char *) result) + sizeof(*result); @@ -300,7 +314,7 @@ const char *osd_get_volume_name(int idx) file_error osd_get_full_path(char **dst, const char *path) { - *dst = (char *)osd_malloc(CCHMAXPATH + 1); + *dst = (char *)osd_malloc_array(CCHMAXPATH + 1); if (*dst == NULL) return FILERR_OUT_OF_MEMORY; diff --git a/src/osd/sdl/sdlos_unix.c b/src/osd/sdl/sdlos_unix.c index 6d2d92032e5..c1ba9baeea5 100644 --- a/src/osd/sdl/sdlos_unix.c +++ b/src/osd/sdl/sdlos_unix.c @@ -93,6 +93,20 @@ void *osd_malloc(size_t size) //============================================================ +// 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 //============================================================ @@ -207,7 +221,7 @@ char *osd_get_clipboard_text(void) /* return a copy & free original */ if (prop != NULL) { - result = (char *) osd_malloc(strlen((char *)prop)+1); + result = (char *) osd_malloc_array(strlen((char *)prop)+1); strcpy(result, (char *)prop); } else @@ -256,7 +270,7 @@ osd_directory_entry *osd_stat(const char *path) // 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(sizeof(*result) + strlen(path) + 1); + 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; @@ -293,7 +307,7 @@ file_error osd_get_full_path(char **dst, const char *path) } else { - *dst = (char *)osd_malloc(strlen(path_buffer)+strlen(path)+3); + *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] == '/') diff --git a/src/osd/sdl/sdlos_win32.c b/src/osd/sdl/sdlos_win32.c index 31be832703b..2ffee467d11 100644 --- a/src/osd/sdl/sdlos_win32.c +++ b/src/osd/sdl/sdlos_win32.c @@ -180,36 +180,49 @@ void *osd_malloc(size_t size) #ifndef MALLOC_DEBUG return HeapAlloc(GetProcessHeap(), 0, size); #else - // add in space for the base pointer + // add in space for the size size += sizeof(size_t); - // small items just come from the heap - void *result; - if (size < GUARD_PAGE_THRESH) - result = HeapAlloc(GetProcessHeap(), 0, size); + // basic objects just come from the heap + void *result = HeapAlloc(GetProcessHeap(), 0, size); - // large items get guard pages - else - { - // round the size up to a page boundary - size_t rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + // store the size and return and pointer to the data afterward + *reinterpret_cast<size_t *>(result) = size; + return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); +#endif +} - // reserve that much memory, plus two guard pages - void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); - if (page_base == NULL) - return NULL; - // now allow access to everything but the first and last pages - page_base = VirtualAlloc(reinterpret_cast<UINT8 *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); - if (page_base == NULL) - return NULL; +//============================================================ +// osd_malloc_array +//============================================================ - // work backwards from the page base to get to the block base - result = GUARD_ALIGN_START ? page_base : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); - } +void *osd_malloc_array(size_t size) +{ +#ifndef MALLOC_DEBUG + return HeapAlloc(GetProcessHeap(), 0, size); +#else + // add in space for the size + size += sizeof(size_t); - // store the page_base at the start - *reinterpret_cast<size_t *>(result) = size; + // round the size up to a page boundary + size_t rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + + // reserve that much memory, plus two guard pages + void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); + if (page_base == NULL) + return NULL; + + // now allow access to everything but the first and last pages + page_base = VirtualAlloc(reinterpret_cast<UINT8 *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); + if (page_base == NULL) + return NULL; + + // work backwards from the page base to get to the block base + void *result = GUARD_ALIGN_START ? page_base : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); + + // store the size at the start with a flag indicating it has a guard page + *reinterpret_cast<size_t *>(result) = size | 0x80000000; return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); #endif } @@ -226,14 +239,14 @@ void osd_free(void *ptr) #else size_t size = reinterpret_cast<size_t *>(ptr)[-1]; - // small items just get freed - if (size < GUARD_PAGE_THRESH) + // if no guard page, just free the pointer + if ((size & 0x80000000) == 0) HeapFree(GetProcessHeap(), 0, reinterpret_cast<UINT8 *>(ptr) - sizeof(size_t)); // large items need more care else { - FPTR page_base = (reinterpret_cast<FPTR>(ptr) - sizeof(size_t)) & ~(PAGE_SIZE - 1); + ULONG_PTR page_base = (reinterpret_cast<ULONG_PTR>(ptr) - sizeof(size_t)) & ~(PAGE_SIZE - 1); VirtualFree(reinterpret_cast<void *>(page_base - PAGE_SIZE), 0, MEM_RELEASE); } #endif @@ -262,7 +275,7 @@ int osd_setenv(const char *name, const char *value, int overwrite) if (osd_getenv(name) != NULL) return 0; } - buf = (char *) osd_malloc(strlen(name)+strlen(value)+2); + buf = (char *) osd_malloc_array(strlen(name)+strlen(value)+2); sprintf(buf, "%s=%s", name, value); result = putenv(buf); @@ -371,7 +384,7 @@ CHAR *astring_from_utf8(const char *utf8string) // convert UTF-16 to "ANSI code page" string char_count = WideCharToMultiByte(CP_ACP, 0, wstring, -1, NULL, 0, NULL, NULL); - result = (CHAR *)osd_malloc(char_count * sizeof(*result)); + result = (CHAR *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) WideCharToMultiByte(CP_ACP, 0, wstring, -1, result, char_count, NULL, NULL); @@ -389,7 +402,7 @@ WCHAR *wstring_from_utf8(const char *utf8string) // convert MAME string (UTF-8) to UTF-16 char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0); - result = (WCHAR *)osd_malloc(char_count * sizeof(*result)); + result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count); diff --git a/src/osd/sdl/sdlwork.c b/src/osd/sdl/sdlwork.c index 4edfcad6463..8959855cc51 100644 --- a/src/osd/sdl/sdlwork.c +++ b/src/osd/sdl/sdlwork.c @@ -183,7 +183,7 @@ osd_work_queue *osd_work_queue_alloc(int flags) queue->threads = MIN(queue->threads, WORK_MAX_THREADS); // allocate memory for thread array (+1 to count the calling thread) - queue->thread = (work_thread_info *)osd_malloc((queue->threads + 1) * sizeof(queue->thread[0])); + queue->thread = (work_thread_info *)osd_malloc_array((queue->threads + 1) * sizeof(queue->thread[0])); if (queue->thread == NULL) goto error; memset(queue->thread, 0, (queue->threads + 1) * sizeof(queue->thread[0])); diff --git a/src/osd/sdl/strconv.c b/src/osd/sdl/strconv.c index 1356b236600..771a302fa92 100644 --- a/src/osd/sdl/strconv.c +++ b/src/osd/sdl/strconv.c @@ -38,7 +38,7 @@ char *utf8_from_astring(const CHAR *astring) // convert UTF-16 to MAME string (UTF-8) char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL); - result = (CHAR *)osd_malloc(char_count * sizeof(*result)); + result = (CHAR *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL); @@ -56,7 +56,7 @@ char *utf8_from_wstring(const WCHAR *wstring) // convert UTF-16 to MAME string (UTF-8) char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL); - result = (char *)osd_malloc(char_count * sizeof(*result)); + result = (char *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL); diff --git a/src/osd/windows/strconv.c b/src/osd/windows/strconv.c index 14cd614951e..0af5fe9c2a3 100644 --- a/src/osd/windows/strconv.c +++ b/src/osd/windows/strconv.c @@ -65,7 +65,7 @@ CHAR *astring_from_utf8(const char *utf8string) // convert UTF-16 to "ANSI code page" string char_count = WideCharToMultiByte(CP_ACP, 0, wstring, -1, NULL, 0, NULL, NULL); - result = (CHAR *)osd_malloc(char_count * sizeof(*result)); + result = (CHAR *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) WideCharToMultiByte(CP_ACP, 0, wstring, -1, result, char_count, NULL, NULL); @@ -90,7 +90,7 @@ char *utf8_from_astring(const CHAR *astring) // convert UTF-16 to MAME string (UTF-8) char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL); - result = (CHAR *)osd_malloc(char_count * sizeof(*result)); + result = (CHAR *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL); @@ -109,7 +109,7 @@ WCHAR *wstring_from_utf8(const char *utf8string) // convert MAME string (UTF-8) to UTF-16 char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0); - result = (WCHAR *)osd_malloc(char_count * sizeof(*result)); + result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count); @@ -128,7 +128,7 @@ char *utf8_from_wstring(const WCHAR *wstring) // convert UTF-16 to MAME string (UTF-8) char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL); - result = (char *)osd_malloc(char_count * sizeof(*result)); + result = (char *)osd_malloc_array(char_count * sizeof(*result)); if (result != NULL) WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL); diff --git a/src/osd/windows/winalloc.c b/src/osd/windows/winalloc.c deleted file mode 100644 index 0fcbee53fbd..00000000000 --- a/src/osd/windows/winalloc.c +++ /dev/null @@ -1,618 +0,0 @@ -//============================================================ -// -// winalloc.c - Win32 memory allocation routines -// -//============================================================ -// -// Copyright Aaron Giles -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or -// without modification, are permitted provided that the -// following conditions are met: -// -// * Redistributions of source code must retain the above -// copyright notice, this list of conditions and the -// following disclaimer. -// * Redistributions in binary form must reproduce the -// above copyright notice, this list of conditions and -// the following disclaimer in the documentation and/or -// other materials provided with the distribution. -// * Neither the name 'MAME' nor the names of its -// contributors may be used to endorse or promote -// products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -//============================================================ - -// standard windows headers -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <tchar.h> - -// MAME headers -#include "osdcore.h" - -// undefine any redefines we have in the prefix -#undef malloc -#undef calloc -#undef realloc - - - -//============================================================ -// CONSTANTS -//============================================================ - -#define OVERRIDE_STANDARD_CALLS (0) - -#define PAGE_SIZE 4096 -#define COOKIE_VAL 0x11335577 - -// set this to 1 to align memory blocks to the start of a page; -// otherwise, they are aligned to the end, thus catching array -// overruns -#define ALIGN_START 0 - -// set this to 1 to record all mallocs and frees in the logfile -#define LOG_CALLS 0 - -#if LOG_CALLS -#define LOG(x) do { if (LOG_CALLS) logerror x; } while (0) -void CLIB_DECL logerror(const char *text,...); -#else -#define LOG(x) -#endif - - -//============================================================ -// TYPEDEFS -//============================================================ - -typedef struct _memory_entry memory_entry; -struct _memory_entry -{ - memory_entry * next; - memory_entry * prev; - size_t size; - void * base; - const char * file; - int line; - int id; -}; - - - -//============================================================ -// GLOBAL VARIABLES -//============================================================ - -int winalloc_in_main_code = FALSE; - - - -//============================================================ -// LOCAL VARIABLES -//============================================================ - -static memory_entry *alloc_list; -static memory_entry *free_list; -static int current_id; - -static CRITICAL_SECTION memory_lock; - -static UINT8 global_init_done = FALSE; -static UINT8 use_malloc_tracking = FALSE; - - - -//============================================================ -// PROTOTYPES -//============================================================ - -static memory_entry *allocate_entry(void); -static memory_entry *find_entry(void *pointer); -static void free_entry(memory_entry *entry); - -static void global_init(void); - - - -//============================================================ -// INLINES -//============================================================ - -INLINE void global_init_if_not_done(void) -{ - if (!global_init_done) - { - global_init_done = TRUE; - global_init(); - } -} - - -INLINE void memory_lock_acquire(void) -{ - EnterCriticalSection(&memory_lock); -} - - -INLINE void memory_lock_release(void) -{ - LeaveCriticalSection(&memory_lock); -} - - - -//============================================================ -// IMPLEMENTATION -//============================================================ - -//============================================================ -// malloc_file_line - debugging version of malloc which -// accepts filename and line number -//============================================================ - -void *malloc_file_line(size_t size, const char *file, int line) -{ - UINT8 *block_base; - int id = current_id++; - - // perform global intialization if not already done - global_init_if_not_done(); - - // only proceed if enabled - if (use_malloc_tracking) - { - UINT8 *page_base; - size_t rounded_size; - memory_entry *entry; - - // round the size up to a page boundary - rounded_size = ((size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; - - // reserve that much memory, plus two guard pages - page_base = (UINT8 *)VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); - if (page_base == NULL) - return NULL; - - // now allow access to everything but the first and last pages - page_base = (UINT8 *)VirtualAlloc(page_base + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); - if (page_base == NULL) - return NULL; - - // work backwards from the page base to get to the block base - if (ALIGN_START) - block_base = page_base; - else - block_base = page_base + rounded_size - size; - - // fill in the entry - entry = allocate_entry(); - entry->size = size; - entry->base = block_base; - entry->file = file; - entry->line = line; - entry->id = id; - } - else - { - block_base = (UINT8 *)GlobalAlloc(GMEM_FIXED, size); - } - - // logging - if (file != NULL) - LOG(("malloc #%06d size = %d (%s:%d)\n", id, size, file, line)); - else - LOG(("malloc #%06d size = %d\n", id, size)); - - return block_base; -} - - -//============================================================ -// malloc - override for the malloc() function -//============================================================ - -#if OVERRIDE_STANDARD_CALLS -void *CLIB_DECL malloc(size_t size) -{ - return malloc_file_line(size, NULL, 0); -} -#endif - - -//============================================================ -// calloc_file_line - debugging version of calloc which -// accepts filename and line number -//============================================================ - -void *calloc_file_line(size_t size, size_t count, const char *file, int line) -{ - // first allocate the memory - void *memory = malloc_file_line(size * count, file, line); - if (memory == NULL) - return NULL; - - // then memset it - memset(memory, 0, size * count); - return memory; -} - - -//============================================================ -// calloc - override for the calloc() function -//============================================================ - -#if OVERRIDE_STANDARD_CALLS -void *CLIB_DECL calloc(size_t size, size_t count) -{ - return calloc_file_line(size, count, NULL, 0); -} -#endif - - -//============================================================ -// _calloc_crt - override for the _calloc_crt() function, -// which is called by beginthreadex -//============================================================ - -#if OVERRIDE_STANDARD_CALLS -void *CLIB_DECL _calloc_crt(size_t size, size_t count) -{ - return calloc_file_line(size, count, NULL, 0); -} -#endif - - -//============================================================ -// realloc_file_line - debugging version of realloc which -// accepts filename and line number -//============================================================ - -void *realloc_file_line(void *memory, size_t size, const char *file, int line) -{ - void *newmemory = NULL; - - // perform global intialization if not already done - global_init_if_not_done(); - - // only proceed if enabled - if (use_malloc_tracking) - { - // if size is non-zero, we need to reallocate memory - if (size != 0) - { - // allocate space for the new amount - newmemory = malloc_file_line(size, file, line); - if (newmemory == NULL) - return NULL; - - // if we have an old pointer, copy it - if (memory != NULL) - { - memory_entry *entry = find_entry(memory); - if (entry == NULL) - { - if (winalloc_in_main_code) - { - fprintf(stderr, "Error: realloc a non-existant block (%s:%d)\n", file, line); - osd_break_into_debugger("Error: realloc a non-existant block\n"); - } - } - else - memcpy(newmemory, memory, (size < entry->size) ? size : entry->size); - } - } - - // if we have an original pointer, free it - if (memory != NULL) - free(memory); - } - else - { - if (memory != NULL) - newmemory = (void *) GlobalReAlloc(memory, size, GMEM_MOVEABLE); - else - newmemory = (void *) GlobalAlloc(GMEM_FIXED, size); - } - - return newmemory; -} - - -//============================================================ -// realloc - override for the realloc() function -//============================================================ - -#if OVERRIDE_STANDARD_CALLS -void *CLIB_DECL realloc(void *memory, size_t size) -{ - return realloc_file_line(memory, size, NULL, 0); -} -#endif - - -//============================================================ -// free_file_line - debugging version of free which -// accepts filename and line number -//============================================================ - -void CLIB_DECL free_file_line(void *memory, const char *file, int line) -{ - memory_entry *entry; - - // allow NULL frees - if (memory == NULL) - return; - - // only proceed if enabled - if (use_malloc_tracking) - { - // error if no entry found - entry = find_entry(memory); - if (entry == NULL) - { - if (winalloc_in_main_code) - { - fprintf(stderr, "Error: free a non-existant block\n"); - osd_break_into_debugger("Error: free a non-existant block"); - } - return; - } - free_entry(entry); - - // free the memory - VirtualFree((UINT8 *)memory - ((size_t)memory & (PAGE_SIZE-1)) - PAGE_SIZE, 0, MEM_RELEASE); - - LOG(("free #%06d size = %d\n", entry->id, entry->size)); - } - else - { - GlobalFree(memory); - } -} - - -//============================================================ -// free - override for the free() function -//============================================================ - -#if OVERRIDE_STANDARD_CALLS -void CLIB_DECL free(void *memory) -{ - free_file_line(memory, NULL, 0); -} -#endif - - -//============================================================ -// _msize - internal MSVC routine that returns the size of -// a memory block -//============================================================ - -#if OVERRIDE_STANDARD_CALLS -size_t CLIB_DECL _msize(void *memory) -{ - size_t result; - - // only proceed if enabled - if (use_malloc_tracking) - { - memory_entry *entry = find_entry(memory); - if (entry == NULL) - { - if (winalloc_in_main_code) - { - fprintf(stderr, "Error: msize a non-existant block\n"); - osd_break_into_debugger("Error: msize a non-existant block"); - } - return 0; - } - result = entry->size; - } - else - { - result = GlobalSize(memory); - } - return result; -} -#endif - - -//============================================================ -// check_unfreed_mem - called from the exit path of any -// code that wants to check for unfreed memory -//============================================================ - -void check_unfreed_mem(void) -{ - memory_entry *entry; - int total = 0; - - // only valid if we are tracking - if (use_malloc_tracking) - { - memory_lock_acquire(); - - // check for leaked memory - for (entry = alloc_list; entry; entry = entry->next) - if (entry->file != NULL) - { - if (total == 0) - fprintf(stderr, "--- memory leak warning ---\n"); - total += entry->size; - fprintf(stderr, "allocation #%06d, %d bytes (%s:%d)\n", entry->id, entry->size, entry->file, (int)entry->line); - } - - memory_lock_release(); - - if (total > 0) - fprintf(stderr, "a total of %d bytes were not free()'d\n", total); - } -} - - -//============================================================ -// allocate_entry - allocate a new entry and link it into -// the list of allocated memory -//============================================================ - -static memory_entry *allocate_entry(void) -{ - memory_entry *entry; - - // always take the lock when allocating - memory_lock_acquire(); - - // if we're out of entries, allocate some more - if (free_list == NULL) - { - int entries_per_page = PAGE_SIZE / sizeof(memory_entry); - - // allocate a new pages' worth of entry - entry = (memory_entry *)VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE); - if (entry == NULL) - { - memory_lock_release(); - fprintf(stderr, "Out of memory for malloc tracking!\n"); - exit(1); - } - - // add all the entries to the list - while (entries_per_page--) - { - entry->next = free_list; - free_list = entry; - entry++; - } - } - - // grab a free list entry - entry = free_list; - free_list = free_list->next; - - // add ourselves to the alloc list - entry->next = alloc_list; - if (entry->next) - entry->next->prev = entry; - entry->prev = NULL; - alloc_list = entry; - - // release the lock when finished - memory_lock_release(); - - return entry; -} - - -//============================================================ -// find_entry - find a memory_object entry in the list that -// contains the given pointer -//============================================================ - -static memory_entry *find_entry(void *pointer) -{ - memory_entry *entry; - - // scan the list looking for a matching base - if (pointer) - { - memory_lock_acquire(); - - for (entry = alloc_list; entry; entry = entry->next) - if (entry->base == pointer) - break; - - memory_lock_release(); - return entry; - } - return NULL; -} - - -//============================================================ -// free_entry - free a memory_entry object -//============================================================ - -static void free_entry(memory_entry *entry) -{ - memory_lock_acquire(); - - // remove ourselves from the alloc list - if (entry->prev) - entry->prev->next = entry->next; - else - alloc_list = entry->next; - if (entry->next) - entry->next->prev = entry->prev; - - // add ourself to the free list - entry->next = free_list; - free_list = entry; - - memory_lock_release(); -} - - -//============================================================ -// global_init - global initialization of memory variables -//============================================================ - -static void global_init(void) -{ - TCHAR *envstring; - - // create the memory lock - InitializeCriticalSection(&memory_lock); - - // determine if we enabled by default - if (win_is_gui_application()) { - use_malloc_tracking = FALSE; - } else { - use_malloc_tracking = TRUE; - } - - // now allow overrides by the environment - envstring = _tgetenv(_T("OSDDEBUGMALLOC")); - if (envstring != NULL) - use_malloc_tracking = (_ttoi(envstring) != 0); - -#ifdef PTR64 - // 64-bit builds also can allocate everything under 4GB, unless disabled - envstring = _tgetenv(_T("OSDDEBUG4GB")); - if (envstring == NULL || _ttoi(envstring) != 0) - { - INT8 allocshift; - - // loop from 256MB down to 4k (page size) - for (allocshift = 8 + 20; allocshift >= 12; allocshift--) - { - // keep allocating address space at that size until we get something >4gb - while ((UINT64)VirtualAlloc(NULL, (UINT64)1 << allocshift, MEM_RESERVE, PAGE_NOACCESS) < ((UINT64)1 << 32)) ; - } - - // loop from 64k down - for (allocshift = 6 + 10; allocshift >= 1; allocshift--) - { - // keep allocating memory until we get something >4gb - while ((UINT64)GlobalAlloc(GMEM_FIXED, (UINT64)1 << allocshift) < ((UINT64)1 << 32)) ; - } - } -#endif -} diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index 8ffb2a29a05..fc3ca77ae69 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -418,7 +418,8 @@ int main(int argc, char *argv[]) { windows_options options; windows_osd_interface osd; - result = cli_execute(options, osd, argc, argv); + cli_frontend frontend(options, osd); + frontend.execute(argc, argv); } // free symbols diff --git a/src/osd/windows/winmisc.c b/src/osd/windows/winmisc.c index 63d8642b8fb..c83613a5e37 100644 --- a/src/osd/windows/winmisc.c +++ b/src/osd/windows/winmisc.c @@ -45,7 +45,7 @@ #include <tchar.h> // MAME headers -#include "emucore.h" +#include "osdcore.h" // MAMEOS headers #include "winutf8.h" @@ -60,9 +60,6 @@ // presumed size of a page of memory #define PAGE_SIZE 4096 -// allocations this size and larger get guard pages -#define GUARD_PAGE_THRESH 32 - // align allocations to start or end of the page? #define GUARD_ALIGN_START 0 @@ -85,36 +82,49 @@ void *osd_malloc(size_t size) #ifndef MALLOC_DEBUG return HeapAlloc(GetProcessHeap(), 0, size); #else - // add in space for the base pointer + // add in space for the size size += sizeof(size_t); - // small items just come from the heap - void *result; - if (size < GUARD_PAGE_THRESH) - result = HeapAlloc(GetProcessHeap(), 0, size); + // basic objects just come from the heap + void *result = HeapAlloc(GetProcessHeap(), 0, size); - // large items get guard pages - else - { - // round the size up to a page boundary - size_t rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + // store the size and return and pointer to the data afterward + *reinterpret_cast<size_t *>(result) = size; + return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); +#endif +} - // reserve that much memory, plus two guard pages - void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); - if (page_base == NULL) - return NULL; - // now allow access to everything but the first and last pages - page_base = VirtualAlloc(reinterpret_cast<UINT8 *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); - if (page_base == NULL) - return NULL; +//============================================================ +// osd_malloc_array +//============================================================ - // work backwards from the page base to get to the block base - result = GUARD_ALIGN_START ? page_base : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); - } +void *osd_malloc_array(size_t size) +{ +#ifndef MALLOC_DEBUG + return HeapAlloc(GetProcessHeap(), 0, size); +#else + // add in space for the size + size += sizeof(size_t); - // store the page_base at the start - *reinterpret_cast<size_t *>(result) = size; + // round the size up to a page boundary + size_t rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + + // reserve that much memory, plus two guard pages + void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); + if (page_base == NULL) + return NULL; + + // now allow access to everything but the first and last pages + page_base = VirtualAlloc(reinterpret_cast<UINT8 *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); + if (page_base == NULL) + return NULL; + + // work backwards from the page base to get to the block base + void *result = GUARD_ALIGN_START ? page_base : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); + + // store the size at the start with a flag indicating it has a guard page + *reinterpret_cast<size_t *>(result) = size | 0x80000000; return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); #endif } @@ -131,14 +141,14 @@ void osd_free(void *ptr) #else size_t size = reinterpret_cast<size_t *>(ptr)[-1]; - // small items just get freed - if (size < GUARD_PAGE_THRESH) + // if no guard page, just free the pointer + if ((size & 0x80000000) == 0) HeapFree(GetProcessHeap(), 0, reinterpret_cast<UINT8 *>(ptr) - sizeof(size_t)); // large items need more care else { - FPTR page_base = (reinterpret_cast<FPTR>(ptr) - sizeof(size_t)) & ~(PAGE_SIZE - 1); + ULONG_PTR page_base = (reinterpret_cast<ULONG_PTR>(ptr) - sizeof(size_t)) & ~(PAGE_SIZE - 1); VirtualFree(reinterpret_cast<void *>(page_base - PAGE_SIZE), 0, MEM_RELEASE); } #endif |