summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/osdcore.h
blob: 141f3db55d94553ec6e3d3a21d874bf56ba506cc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    osdcore.h

    Core OS-dependent code interface.

****************************************************************************

    The prototypes in this file describe the interfaces that the MAME core
    and various tools rely upon to interact with the outside world. They are
    broken out into several categories.

***************************************************************************/

#pragma once

#ifndef MAME_OSD_OSDCORE_H
#define MAME_OSD_OSDCORE_H

#include "osdcomm.h"

#include <chrono>
#include <cstdarg>
#include <cstdint>
#include <memory>
#include <string>


/***************************************************************************
    FILE I/O INTERFACES
***************************************************************************/

/* Make sure we have a path separator (default to /) */
#ifndef PATH_SEPARATOR
#if defined(_WIN32)
#define PATH_SEPARATOR          "\\"
#else
#define PATH_SEPARATOR          "/"
#endif
#endif

/* flags controlling file access */
#define OPEN_FLAG_READ          0x0001      /* open for read */
#define OPEN_FLAG_WRITE         0x0002      /* open for write */
#define OPEN_FLAG_CREATE        0x0004      /* create & truncate file */
#define OPEN_FLAG_CREATE_PATHS  0x0008      /* create paths as necessary */
#define OPEN_FLAG_NO_PRELOAD    0x0010      /* do not decompress on open */

// osd_file is an interface which represents an open file/PTY/socket
class osd_file
{
public:
	// error codes returned by routines below
	enum class error
	{
		NONE,
		FAILURE,
		OUT_OF_MEMORY,
		NOT_FOUND,
		ACCESS_DENIED,
		ALREADY_OPEN,
		TOO_MANY_FILES,
		INVALID_DATA,
		INVALID_ACCESS
	};

	typedef std::unique_ptr<osd_file> ptr;


	/*-----------------------------------------------------------------------------
	    osd_file::open: open a new file.

	    Parameters:

	        path - path to the file to open

	        openflags - some combination of:

	            OPEN_FLAG_READ - open the file for read access
	            OPEN_FLAG_WRITE - open the file for write access
	            OPEN_FLAG_CREATE - create/truncate the file when opening
	            OPEN_FLAG_CREATE_PATHS - specifies that non-existant paths
	                    should be created if necessary

	        file - reference to an osd_file::ptr to receive the newly-opened file
	            handle; this is only valid if the function returns FILERR_NONE

	        filesize - reference to a UINT64 to receive the size of the opened
	            file; this is only valid if the function returns FILERR_NONE

	    Return value:

	        a file_error describing any error that occurred while opening
	        the file, or FILERR_NONE if no error occurred

	    Notes:

	        This function is called by core_fopen and several other places in
	        the core to access files. These functions will construct paths by
	        concatenating various search paths held in the options.c options
	        database with partial paths specified by the core. The core assumes
	        that the path separator is the first character of the string
	        PATH_SEPARATOR, but does not interpret any path separators in the
	        search paths, so if you use a different path separator in a search
	        path, you may get a mixture of PATH_SEPARATORs (from the core) and
	        alternate path separators (specified by users and placed into the
	        options database).
	-----------------------------------------------------------------------------*/
	static error open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize);


	/*-----------------------------------------------------------------------------
	    osd_file::openpty: create a new PTY pair

	    Parameters:

	        file - reference to an osd_file::ptr to receive the handle of the master
	            side of the newly-created PTY; this is only valid if the function
	            returns FILERR_NONE

	        name - reference to string where slave filename will be stored

	    Return value:

	        a file_error describing any error that occurred while creating the
	        PTY, or FILERR_NONE if no error occurred
	-----------------------------------------------------------------------------*/
	static error openpty(ptr &file, std::string &name);


	/*-----------------------------------------------------------------------------
	    osd_file::~osd_file: close an open file
	-----------------------------------------------------------------------------*/
	virtual ~osd_file() { }


	/*-----------------------------------------------------------------------------
	    osd_file::read: read from an open file

	    Parameters:

	        buffer - pointer to memory that will receive the data read

	        offset - offset within the file to read from

	        length - number of bytes to read from the file

	        actual - reference to a UINT32 to receive the number of bytes actually
	            read during the operation; valid only if the function returns
	            FILERR_NONE

	    Return value:

	        a file_error describing any error that occurred while reading
	        from the file, or FILERR_NONE if no error occurred
	-----------------------------------------------------------------------------*/
	virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0;


	/*-----------------------------------------------------------------------------
	    osd_file::write: write to an open file

	    Parameters:

	        buffer - pointer to memory that contains the data to write

	        offset - offset within the file to write to

	        length - number of bytes to write to the file

	        actual - reference to a UINT32 to receive the number of bytes actually
	            written during the operation; valid only if the function returns
	            FILERR_NONE

	    Return value:

	        a file_error describing any error that occurred while writing to
	        the file, or FILERR_NONE if no error occurred
	-----------------------------------------------------------------------------*/
	virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0;


	/*-----------------------------------------------------------------------------
	    osd_file::truncate: change the size of an open file

	    Parameters:

.           offset - future size of the file

	    Return value:

	        a file_error describing any error that occurred while writing to
	        the file, or FILERR_NONE if no error occurred
	-----------------------------------------------------------------------------*/
	virtual error truncate(std::uint64_t offset) = 0;


	/*-----------------------------------------------------------------------------
	    osd_file::flush: flush file buffers

	    Parameters:

	        file - handle to a file previously opened via osd_open

	    Return value:

	        a file_error describing any error that occurred while flushing file
	        buffers, or FILERR_NONE if no error occurred
	-----------------------------------------------------------------------------*/
	virtual error flush() = 0;


	/*-----------------------------------------------------------------------------
	    osd_file::remove: deletes a file

	    Parameters:

	        filename - path to file to delete

	    Return value:

	        a file_error describing any error that occurred while deleting
	        the file, or FILERR_NONE if no error occurred
	-----------------------------------------------------------------------------*/
	static error remove(std::string const &filename);
};



/*-----------------------------------------------------------------------------
    osd_getenv: return pointer to environment variable

    Parameters:

        name  - name of environment variable

    Return value:

        pointer to value
-----------------------------------------------------------------------------*/
const char *osd_getenv(const char *name);


/*-----------------------------------------------------------------------------
    osd_get_physical_drive_geometry: if the given path points to a physical
        drive, return the geometry of that drive

    Parameters:

        filename - pointer to a path which might describe a physical drive

        cylinders - pointer to a UINT32 to receive the number of cylinders
            of the physical drive

        heads - pointer to a UINT32 to receive the number of heads per
            cylinder of the physical drive

        sectors - pointer to a UINT32 to receive the number of sectors per
            cylinder of the physical drive

        bps - pointer to a UINT32 to receive the number of bytes per sector
            of the physical drive

    Return value:

        TRUE if the filename points to a physical drive and if the values
        pointed to by cylinders, heads, sectors, and bps are valid; FALSE in
        any other case
-----------------------------------------------------------------------------*/
int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps);


/*-----------------------------------------------------------------------------
    osd_uchar_from_osdchar: convert the given character or sequence of
        characters from the OS-default encoding to a Unicode character

    Parameters:

        uchar - pointer to a UINT32 to receive the resulting unicode
            character

        osdchar - pointer to one or more chars that are in the OS-default
            encoding

        count - number of characters provided in the OS-default encoding

    Return value:

        The number of characters required to form a Unicode character.
-----------------------------------------------------------------------------*/
int osd_uchar_from_osdchar(UINT32 /* unicode_char */ *uchar, const char *osdchar, size_t count);



/***************************************************************************
    DIRECTORY INTERFACES
***************************************************************************/

namespace osd
{
	// directory is an opaque type which represents an open directory
	class directory
	{
	public:
		typedef std::unique_ptr<directory> ptr;

		// osd::directory::entry contains basic information about a file when iterating through
		// a directory
		class entry
		{
		public:
			enum class entry_type
			{
				NONE,
				FILE,
				DIR,
				OTHER
			};

			const char *							name;           // name of the entry
			entry_type								type;           // type of the entry
			std::uint64_t							size;           // size of the entry
			std::chrono::system_clock::time_point	last_modified;	// last modified time
		};

		// -----------------------------------------------------------------------------
		// osd::directory::open: open a directory for iteration
		// 
		// Parameters:
		// 
		// dirname - path to the directory in question
		// 
		// Return value:
		// 
		// upon success, this function should return an directory pointer
		// which contains opaque data necessary to traverse the directory; on
		// failure, this function should return nullptr
		// -----------------------------------------------------------------------------
		static ptr open(std::string const &dirname);

		// -----------------------------------------------------------------------------
		// osd::directory::~directory: close an open directory
		// -----------------------------------------------------------------------------
		virtual ~directory() { }

		// -----------------------------------------------------------------------------
		// osd::directory::read: return information about the next entry in the directory
		// 
		// Return value:
		// 
		// a constant pointer to an entry representing the current item
		// in the directory, or nullptr, indicating that no more entries are
		// present
		// -----------------------------------------------------------------------------
		virtual const entry *read() = 0;
	};
};


/*-----------------------------------------------------------------------------
    osd_is_absolute_path: returns whether the specified path is absolute

    Parameters:

        path - the path in question

    Return value:

        non-zero if the path is absolute, zero otherwise
-----------------------------------------------------------------------------*/
bool osd_is_absolute_path(const std::string &path);



/***************************************************************************
    TIMING INTERFACES
***************************************************************************/

/* a osd_ticks_t is a 64-bit unsigned integer that is used as a core type in timing interfaces */
typedef UINT64 osd_ticks_t;


/*-----------------------------------------------------------------------------
    osd_ticks: return the current running tick counter

    Parameters:

        None

    Return value:

        an osd_ticks_t value which represents the current tick counter

    Notes:

        The resolution of this counter should be 1ms or better for accurate
        performance. It is also important that the source of this timer be
        accurate. It is ok if this call is not ultra-fast, since it is
        primarily used for once/frame synchronization.
-----------------------------------------------------------------------------*/
osd_ticks_t osd_ticks(void);


/*-----------------------------------------------------------------------------
    osd_ticks_per_second: return the number of ticks per second

    Parameters:

        None

    Return value:

        an osd_ticks_t value which represents the number of ticks per
        second
-----------------------------------------------------------------------------*/
osd_ticks_t osd_ticks_per_second(void);


/*-----------------------------------------------------------------------------
    osd_sleep: sleep for the specified time interval

    Parameters:

        duration - an osd_ticks_t value that specifies how long we should
            sleep

    Return value:

        None

    Notes:

        The OSD layer should try to sleep for as close to the specified
        duration as possible, or less. This is used as a mechanism to
        "give back" unneeded time to other programs running in the system.
        On a simple, non multitasking system, this routine can be a no-op.
        If there is significant volatility in the amount of time that the
        sleep occurs for, the OSD layer should strive to sleep for less time
        than specified rather than sleeping too long.
-----------------------------------------------------------------------------*/
void osd_sleep(osd_ticks_t duration);

/***************************************************************************
    WORK ITEM INTERFACES
***************************************************************************/

/* this is the maximum number of supported threads for a single work queue */
/* threadid values are expected to range from 0..WORK_MAX_THREADS-1 */
#define WORK_MAX_THREADS            16

/* these flags can be set when creating a queue to give hints to the code about
   how to configure the queue */
#define WORK_QUEUE_FLAG_IO          0x0001
#define WORK_QUEUE_FLAG_MULTI       0x0002
#define WORK_QUEUE_FLAG_HIGH_FREQ   0x0004

/* these flags can be set when queueing a work item to indicate how to handle
   its deconstruction */
#define WORK_ITEM_FLAG_AUTO_RELEASE 0x0001

/* osd_work_queue is an opaque type which represents a queue of work items */
struct osd_work_queue;

/* osd_work_item is an opaque type which represents a single work item */
struct osd_work_item;

/* osd_work_callback is a callback function that does work */
typedef void *(*osd_work_callback)(void *param, int threadid);


/*-----------------------------------------------------------------------------
    osd_work_queue_alloc: create a new work queue

    Parameters:

        flags - one or more of the WORK_QUEUE_FLAG_* values ORed together:

            WORK_QUEUE_FLAG_IO - indicates that the work queue will do some
                I/O; this may be a useful hint so that threads are created
                even on single-processor systems since I/O can often be
                overlapped with other work

            WORK_QUEUE_FLAG_MULTI - indicates that the work queue should
                take advantage of as many processors as it can; items queued
                here are assumed to be fully independent or shared

            WORK_QUEUE_FLAG_HIGH_FREQ - indicates that items are expected
                to be queued at high frequency and acted upon quickly; in
                general, this implies doing some spin-waiting internally
                before falling back to OS-specific synchronization

    Return value:

        A pointer to an allocated osd_work_queue object.

    Notes:

        A work queue abstracts the notion of how potentially threaded work
        can be performed. If no threading support is available, it is a
        simple matter to execute the work items as they are queued.
-----------------------------------------------------------------------------*/
osd_work_queue *osd_work_queue_alloc(int flags);


/*-----------------------------------------------------------------------------
    osd_work_queue_items: return the number of pending items in the queue

    Parameters:

        queue - pointer to an osd_work_queue that was previously created via
            osd_work_queue_alloc

    Return value:

        The number of incomplete items remaining in the queue.
-----------------------------------------------------------------------------*/
int osd_work_queue_items(osd_work_queue *queue);


/*-----------------------------------------------------------------------------
    osd_work_queue_wait: wait for the queue to be empty

    Parameters:

        queue - pointer to an osd_work_queue that was previously created via
            osd_work_queue_alloc

        timeout - a timeout value in osd_ticks_per_second()

    Return value:

        TRUE if the queue is empty; FALSE if the wait timed out before the
        queue was emptied.
-----------------------------------------------------------------------------*/
int osd_work_queue_wait(osd_work_queue *queue, osd_ticks_t timeout);


/*-----------------------------------------------------------------------------
    osd_work_queue_free: free a work queue, waiting for all items to complete

    Parameters:

        queue - pointer to an osd_work_queue that was previously created via
            osd_work_queue_alloc

    Return value:

        None.
-----------------------------------------------------------------------------*/
void osd_work_queue_free(osd_work_queue *queue);


/*-----------------------------------------------------------------------------
    osd_work_item_queue_multiple: queue a set of work items

    Parameters:

        queue - pointer to an osd_work_queue that was previously created via
            osd_work_queue_alloc

        callback - pointer to a function that will do the work

        numitems - number of work items to queue

        param - a void * parameter that can be used to pass data to the
            function

        paramstep - the number of bytes to increment param by for each item
            queued; for example, if you have an array of work_unit objects,
            you can point param to the base of the array and set paramstep to
            sizeof(work_unit)

        flags - one or more of the WORK_ITEM_FLAG_* values ORed together:

            WORK_ITEM_FLAG_AUTO_RELEASE - indicates that the work item
                should be automatically freed when it is complete

    Return value:

        A pointer to the final allocated osd_work_item in the list.

    Notes:

        On single-threaded systems, this function may actually execute the
        work item immediately before returning.
-----------------------------------------------------------------------------*/
osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_callback callback, INT32 numitems, void *parambase, INT32 paramstep, UINT32 flags);


/* inline helper to queue a single work item using the same interface */
static inline osd_work_item *osd_work_item_queue(osd_work_queue *queue, osd_work_callback callback, void *param, UINT32 flags)
{
	return osd_work_item_queue_multiple(queue, callback, 1, param, 0, flags);
}


/*-----------------------------------------------------------------------------
    osd_work_item_wait: wait for a work item to complete

    Parameters:

        item - pointer to an osd_work_item that was previously returned from
            osd_work_item_queue

        timeout - a timeout value in osd_ticks_per_second()

    Return value:

        TRUE if the item completed; FALSE if the wait timed out before the
        item completed.
-----------------------------------------------------------------------------*/
int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout);


/*-----------------------------------------------------------------------------
    osd_work_item_result: get the result of a work item

    Parameters:

        item - pointer to an osd_work_item that was previously returned from
            osd_work_item_queue

    Return value:

        A void * that represents the work item's result.
-----------------------------------------------------------------------------*/
void *osd_work_item_result(osd_work_item *item);


/*-----------------------------------------------------------------------------
    osd_work_item_release: release the memory allocated to a work item

    Parameters:

        item - pointer to an osd_work_item that was previously returned from
            osd_work_item_queue

    Return value:

        None.

    Notes:

        The osd_work_item exists until explicitly released, even if it has
        long since completed. It is the queuer's responsibility to release
        any work items it has queued.
-----------------------------------------------------------------------------*/
void osd_work_item_release(osd_work_item *item);



/***************************************************************************
    MISCELLANEOUS INTERFACES
***************************************************************************/

/*-----------------------------------------------------------------------------
    osd_malloc: allocate memory

    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(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:

        ptr - the pointer returned from osd_mallo

    Return value:

        None
-----------------------------------------------------------------------------*/
void osd_free(void *ptr);


/*-----------------------------------------------------------------------------
    osd_alloc_executable: allocate memory that can contain executable code

    Parameters:

        size - the number of bytes to allocate

    Return value:

        a pointer to the allocated memory

    Notes:

        On many systems, this call may acceptably map to malloc(). On systems
        where pages are tagged with "no execute" privileges, it may be
        necessary to perform some kind of special allocation to ensure that
        code placed into this buffer can be executed.
-----------------------------------------------------------------------------*/
void *osd_alloc_executable(size_t size);


/*-----------------------------------------------------------------------------
    osd_free_executable: free memory allocated by osd_alloc_executable

    Parameters:

        ptr - the pointer returned from osd_alloc_executable

        size - the number of bytes originally requested

    Return value:

        None
-----------------------------------------------------------------------------*/
void osd_free_executable(void *ptr, size_t size);


/*-----------------------------------------------------------------------------
    osd_break_into_debugger: break into the hosting system's debugger if one
        is attached

    Parameters:

        message - pointer to string to output to the debugger

    Return value:

        None.

    Notes:

        This function is called when an assertion or other important error
        occurs. If a debugger is attached to the current process, it should
        break into the debugger and display the given message.
-----------------------------------------------------------------------------*/
void osd_break_into_debugger(const char *message);

/*-----------------------------------------------------------------------------
    osd_get_clipboard_text: retrieves text from the clipboard

    Return value:

        the returned string needs to be osd_free()-ed!

-----------------------------------------------------------------------------*/
char *osd_get_clipboard_text(void);


/***************************************************************************
    DIRECTORY INTERFACES
***************************************************************************/

/*-----------------------------------------------------------------------------
    osd_stat: return a directory entry for a path

    Parameters:

        path - path in question

    Return value:

        an allocated pointer to an osd::directory::entry representing
        info on the path; even if the file does not exist.

-----------------------------------------------------------------------------*/
std::unique_ptr<osd::directory::entry> osd_stat(std::string const &path);

/***************************************************************************
    PATH INTERFACES
***************************************************************************/

/*-----------------------------------------------------------------------------
    osd_get_full_path: retrieves the full path

    Parameters:

        path - the path in question
        dst - reference to receive new path

    Return value:

        file error

-----------------------------------------------------------------------------*/
osd_file::error osd_get_full_path(std::string &dst, std::string const &path);


/***************************************************************************
    MIDI I/O INTERFACES
***************************************************************************/

class osd_midi_device
{
public:
	virtual ~osd_midi_device() { }
	// free result with osd_close_midi_channel()
	virtual bool open_input(const char *devname) = 0;
	// free result with osd_close_midi_channel()
	virtual bool open_output(const char *devname) = 0;
	virtual void close() = 0;
	virtual bool poll() = 0;
	virtual int read(UINT8 *pOut) = 0;
	virtual void write(UINT8 data) = 0;
};

//FIXME: really needed here?
void osd_list_network_adapters(void);

/***************************************************************************
    UNCATEGORIZED INTERFACES
***************************************************************************/

/*-----------------------------------------------------------------------------
    osd_get_volume_name: retrieves the volume name

    Parameters:

        idx - order number of volume

    Return value:

        pointer to volume name

-----------------------------------------------------------------------------*/
const char *osd_get_volume_name(int idx);

/*-----------------------------------------------------------------------------
    osd_subst_env: substitute environment variables with values

    Parameters:

        dst - result pointer
        src - source string

-----------------------------------------------------------------------------*/
void osd_subst_env(std::string &dst,std::string const &src);

/* ----- output management ----- */

// output channels
enum osd_output_channel
{
	OSD_OUTPUT_CHANNEL_ERROR,
	OSD_OUTPUT_CHANNEL_WARNING,
	OSD_OUTPUT_CHANNEL_INFO,
	OSD_OUTPUT_CHANNEL_DEBUG,
	OSD_OUTPUT_CHANNEL_VERBOSE,
	OSD_OUTPUT_CHANNEL_LOG,
	OSD_OUTPUT_CHANNEL_COUNT
};

class osd_output
{
public:
	osd_output() : m_chain(nullptr) { }
	virtual ~osd_output() { }

	virtual void output_callback(osd_output_channel channel, const char *msg, va_list args) = 0;

	static void push(osd_output *delegate);
	static void pop(osd_output *delegate);
protected:

	void chain_output(osd_output_channel channel, const char *msg, va_list args) const
	{
		if (m_chain != nullptr)
			m_chain->output_callback(channel, msg, args);
	}
private:
	osd_output *m_chain;
};

/* calls to be used by the code */
void CLIB_DECL osd_printf_error(const char *format, ...) ATTR_PRINTF(1,2);
void CLIB_DECL osd_printf_warning(const char *format, ...) ATTR_PRINTF(1,2);
void CLIB_DECL osd_printf_info(const char *format, ...) ATTR_PRINTF(1,2);
void CLIB_DECL osd_printf_verbose(const char *format, ...) ATTR_PRINTF(1,2);
void CLIB_DECL osd_printf_debug(const char *format, ...) ATTR_PRINTF(1,2);

/* discourage the use of printf directly */
/* sadly, can't do this because of the ATTR_PRINTF under GCC */
/*
#undef printf
#define printf !MUST_USE_osd_printf_*_CALLS_WITHIN_THE_CORE!
*/

#endif // MAME_OSD_OSDCORE_H