Previous 199869 Revisions Next

r26377 Saturday 23rd November, 2013 at 13:54:22 UTC by Jürgen Buchmüller
Extend attrib to 32 bits and add glyph width mask (yet unused). Add support for Unicode in dvstate m_symbol and valstr. Use header arrows and check boxes in dvbpoints.
[/branches/alto2/src/emu/debug]debugvw.h dvbpoints.c dvstate.c dvstate.h dvtext.h textbuf.c textbuf.h
[/branches/alto2/src/lib/util]unicode.c unicode.h

branches/alto2/src/emu/debug/dvbpoints.c
r26376r26377
345345
346346   // Draw
347347   debug_view_char *dest = m_viewdata;
348   size_t width = 256;
349   unicode_char buffer[256+1];
348350   for (int row = 0; row < m_visible.y; row++)
349351   {
350352      UINT32 effrow = m_topleft.y + row;
353      for (size_t i = 0; i < width; i++)
354         buffer[i] = ' ';
351355
352356      // Header
353357      if (row == 0)
354358      {
355         astring header;
356         header.printf("ID");
357         if (m_sortType == SORT_INDEX_ASCENDING) header.catprintf("\\");
358         else if (m_sortType == SORT_INDEX_DESCENDING) header.catprintf("/");
359         pad_astring_to_length(header, tableBreaks[0]);
360         header.catprintf("En");
361         if (m_sortType == SORT_ENABLED_ASCENDING) header.catprintf("\\");
362         else if (m_sortType == SORT_ENABLED_DESCENDING) header.catprintf("/");
363         pad_astring_to_length(header, tableBreaks[1]);
364         header.catprintf("CPU");
365         if (m_sortType == SORT_CPU_ASCENDING) header.catprintf("\\");
366         else if (m_sortType == SORT_CPU_DESCENDING) header.catprintf("/");
367         pad_astring_to_length(header, tableBreaks[2]);
368         header.catprintf("Address");
369         if (m_sortType == SORT_ADDRESS_ASCENDING) header.catprintf("\\");
370         else if (m_sortType == SORT_ADDRESS_DESCENDING) header.catprintf("/");
371         pad_astring_to_length(header, tableBreaks[3]);
372         header.catprintf("Condition");
373         if (m_sortType == SORT_CONDITION_ASCENDING) header.catprintf("\\");
374         else if (m_sortType == SORT_CONDITION_DESCENDING) header.catprintf("/");
375         pad_astring_to_length(header, tableBreaks[4]);
376         header.catprintf("Action");
377         if (m_sortType == SORT_ACTION_ASCENDING) header.catprintf("\\");
378         else if (m_sortType == SORT_ACTION_DESCENDING) header.catprintf("/");
379         pad_astring_to_length(header, tableBreaks[5]);
359         const unicode_char up_arrow = 0x25b2;   // BLACK UP-POINTING TRIANGLE "▲"
360         const unicode_char down_arrow = 0x25bc;   // BLACK DOWN-POINTING TRIANGLE "▼"
361         int col = uchar_snprintf(buffer, width, "ID");
362         if (m_sortType == SORT_INDEX_ASCENDING) buffer[col++] = down_arrow;
363         else if (m_sortType == SORT_INDEX_DESCENDING) buffer[col++] = up_arrow;
364         col = tableBreaks[0];
365         col += uchar_snprintf(&buffer[col], width - col, "En");
366         if (m_sortType == SORT_ENABLED_ASCENDING) buffer[col] = down_arrow;
367         else if (m_sortType == SORT_ENABLED_DESCENDING) buffer[col] = up_arrow;
368         col = tableBreaks[1];
369         col += uchar_snprintf(&buffer[col], width - col, "CPU");
370         if (m_sortType == SORT_CPU_ASCENDING) buffer[col] = down_arrow;
371         else if (m_sortType == SORT_CPU_DESCENDING) buffer[col] = up_arrow;
372         col = tableBreaks[2];
373         col += uchar_snprintf(&buffer[col], width - col, "Address");
374         if (m_sortType == SORT_ADDRESS_ASCENDING) buffer[col] = down_arrow;
375         else if (m_sortType == SORT_ADDRESS_DESCENDING) buffer[col] = up_arrow;
376         col = tableBreaks[3];
377         col += uchar_snprintf(&buffer[col], width - col, "Condition");
378         if (m_sortType == SORT_CONDITION_ASCENDING) buffer[col] = down_arrow;
379         else if (m_sortType == SORT_CONDITION_DESCENDING) buffer[col] = up_arrow;
380         col = tableBreaks[4];
381         col += uchar_snprintf(&buffer[col], width - col, "Action");
382         if (m_sortType == SORT_ACTION_ASCENDING) buffer[col] = down_arrow;
383         else if (m_sortType == SORT_ACTION_DESCENDING) buffer[col] = up_arrow;
380384
381         for (int i = 0; i < m_visible.x; i++)
382         {
383            dest->uchar = (i < header.len()) ? header[i] : ' ';
385         for (size_t i = 0; i < m_visible.x && i < width; i++) {
386            dest->uchar = buffer[i];
384387            dest->attrib = DCA_ANCILLARY;
385388            dest++;
386389         }
r26376r26377
391394      int bpi = effrow-1;
392395      if (bpi < numBPs && bpi >= 0)
393396      {
397         const unicode_char checked = 0x25a3;      // WHITE SQUARE CONTAINING BLACK SMALL SQUARE "▣"
398         const unicode_char unchecked = 0x25a1;      // WHITE SQUARE "□"
394399         device_debug::breakpoint* bp = bpList[bpi];
395
396         astring buffer;
397         buffer.printf("%x", bp->index());
398         pad_astring_to_length(buffer, tableBreaks[0]);
399         buffer.catprintf("%c", bp->enabled() ? 'X' : 'O');
400         pad_astring_to_length(buffer, tableBreaks[1]);
401         buffer.catprintf("%s", bp->debugInterface()->device().tag());
402         pad_astring_to_length(buffer, tableBreaks[2]);
403         buffer.catprintf("%s", core_i64_hex_format(bp->address(), bp->debugInterface()->logaddrchars()));
404         pad_astring_to_length(buffer, tableBreaks[3]);
400         uchar_snprintf(buffer, width, "%x", bp->index());
401         int col = tableBreaks[0];
402         buffer[col] = bp->enabled() ? checked : unchecked;
403         col = tableBreaks[1];
404         uchar_snprintf(&buffer[col], width - col, "%s", bp->debugInterface()->device().tag());
405         col = tableBreaks[2];
406         uchar_snprintf(&buffer[col], width - col, "%s", core_i64_hex_format(bp->address(), bp->debugInterface()->logaddrchars()));
407         col = tableBreaks[3];
405408         if (astring(bp->condition()) != astring("1"))
406         {
407            buffer.catprintf("%s", bp->condition());
408            pad_astring_to_length(buffer, tableBreaks[4]);
409         }
409            uchar_snprintf(&buffer[col], width - col, "%s", bp->condition());
410         col = tableBreaks[4];
410411         if (astring(bp->action()) != astring(""))
411         {
412            buffer.catprintf("%s", bp->action());
413            pad_astring_to_length(buffer, tableBreaks[5]);
414         }
412            uchar_snprintf(&buffer[col], width - col, "%s", bp->action());
415413
416         for (int i = 0; i < m_visible.x; i++)
417         {
418            dest->uchar = (i < buffer.len()) ? buffer[i] : ' ';
414         for (size_t i = 0; i < m_visible.x && i < width; i++) {
415            dest->uchar = buffer[i];
419416            dest->attrib = DCA_NORMAL;
420
421417            // Color disabled breakpoints red
422            if (i == 5 && dest->uchar == 'O')
418            if (i == tableBreaks[0] && !bp->enabled())
423419               dest->attrib = DCA_CHANGED;
424
425420            dest++;
426421         }
427422         continue;
branches/alto2/src/emu/debug/debugvw.h
r26376r26377
4646
4747
4848// attribute bits for debug_view_char.attrib
49const UINT8 DCA_NORMAL      = 0x00;     //!< black on white
50const UINT8 DCA_CHANGED     = 0x01;     //!< red foreground
51const UINT8 DCA_SELECTED    = 0x02;     //!< light red background
52const UINT8 DCA_INVALID     = 0x04;     //!< dark blue foreground
53const UINT8 DCA_DISABLED    = 0x08;     //!< darker foreground
54const UINT8 DCA_ANCILLARY   = 0x10;     //!< grey background
55const UINT8 DCA_CURRENT     = 0x20;     //!< yellow background
56const UINT8 DCA_COMMENT     = 0x40;     //!< green foreground
57const UINT8 DCA_VISITED     = 0x80;     //!< light blue background
49const UINT32 DCA_NORMAL      = 0;             //!< black on white
50const UINT32 DCA_CHANGED     = (1 <<  0);     //!< red foreground
51const UINT32 DCA_SELECTED    = (1 <<  1);     //!< light red background
52const UINT32 DCA_INVALID     = (1 <<  2);     //!< dark blue foreground
53const UINT32 DCA_DISABLED    = (1 <<  3);     //!< darker foreground
54const UINT32 DCA_ANCILLARY   = (1 <<  4);     //!< grey background
55const UINT32 DCA_CURRENT     = (1 <<  5);     //!< yellow background
56const UINT32 DCA_COMMENT     = (1 <<  6);     //!< green foreground
57const UINT32 DCA_VISITED     = (1 <<  7);     //!< light blue background
58const UINT32 DCA_WIDTH_MASK  = (3 << 30);     //!< width of the glyph in cells
5859
5960
6061// special characters that can be passed to process_char()
r26376r26377
9091typedef void (*debug_view_osd_update_func)(debug_view &view, void *osdprivate);
9192
9293
93//! a single "character" in the debug view has an Unicode value and an attribute byte
94//! a single "character" in the debug view has an Unicode value and an attribute flags
9495struct debug_view_char
9596{
9697   unicode_char        uchar;
97   UINT8               attrib;
98   UINT32              attrib;
9899};
99100
100101
branches/alto2/src/emu/debug/dvstate.c
r26376r26377
160160   for (state_item *item = m_state_list; item != NULL; item = item->m_next)
161161   {
162162      count++;
163      maxtaglen = MAX(maxtaglen, item->m_symbol.len());
163      maxtaglen = MAX(maxtaglen, item->m_symbol_w);
164164      maxvallen = MAX(maxvallen, item->m_vallen);
165165   }
166166
r26376r26377
221221      if (curitem != NULL)
222222      {
223223         UINT32 effcol = m_topleft.x;
224         UINT8 attrib = DCA_NORMAL;
224         UINT32 attrib = DCA_NORMAL;
225225         UINT32 len = 0;
226226         astring valstr;
227227
r26376r26377
236236                  curitem->m_symbol.reset();
237237                  for (int i = 0; i < m_total.x; i++)
238238                     curitem->m_symbol.cat("-");
239                  curitem->m_symbol_w = utf8_width(curitem->m_symbol.cstr());
239240                  break;
240241
241242               case REG_CYCLES:
r26376r26377
283284         if (curitem->m_lastval != curitem->m_currval)
284285            attrib = DCA_CHANGED;
285286
286         // build up a string
287         char temp[256];
288         if (curitem->m_symbol.len() < m_divider - 1)
289         {
290            memset(&temp[len], ' ', m_divider - 1 - curitem->m_symbol.len());
291            len += m_divider - 1 - curitem->m_symbol.len();
292         }
293
294         memcpy(&temp[len], curitem->m_symbol.cstr(), curitem->m_symbol.len());
295         len += curitem->m_symbol.len();
296
297         temp[len++] = ' ';
298         temp[len++] = ' ';
299
300         memcpy(&temp[len], valstr.cstr(), curitem->m_vallen);
301         len += curitem->m_vallen;
302
303         temp[len++] = ' ';
287         // build up a unciode_char string
288         unicode_char temp[256];
289         for (int i = 0; i < ARRAY_LENGTH(temp); i++)
290            temp[i] = ' ';
291         len = curitem->m_symbol_w > m_divider - 1 ? 0 : m_divider - 1 - curitem->m_symbol_w;
292         // decode symbol UTF-8 to unicode values
293         len += ustring_from_utf8(&temp[len], ARRAY_LENGTH(temp) - len, curitem->m_symbol.cstr());
294         len += 2;
295         // decode value UTF-8 to unicode values
296         len += ustring_from_utf8(&temp[len], ARRAY_LENGTH(temp) - len, valstr.cstr());
297         len += 1;
304298         temp[len] = 0;
305299
306300         // copy data
r26376r26377
341335      m_currval(0),
342336      m_index(index),
343337      m_vallen(valuechars),
344      m_symbol(name)
338      m_symbol(name),
339      m_symbol_w(utf8_width(name))
345340{
346341}
branches/alto2/src/emu/debug/dvstate.h
r26376r26377
22// copyright-holders:Aaron Giles
33/*********************************************************************
44
5    dvstate.h
5   dvstate.h
66
7    State debugger view.
7   State debugger view.
88
99***************************************************************************/
1010
r26376r26377
6464      int                 m_index;            // index
6565      UINT8               m_vallen;           // number of value chars
6666      astring             m_symbol;           // symbol
67      size_t              m_symbol_w;     // width of the symbol in unicode glyphs
6768   };
6869
6970   // internal helpers
branches/alto2/src/emu/debug/textbuf.c
r26376r26377
8181   text_buffer_alloc - allocate a new text buffer
8282-------------------------------------------------*/
8383
84text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines)
84text_buffer *text_buffer_alloc(UINT32 columns, UINT32 lines)
8585{
8686   text_buffer *text;
8787
r26376r26377
9191      return NULL;
9292
9393   /* allocate memory for the buffer itself */
94   text->buffer = (unicode_char *)osd_malloc_array(sizeof(unicode_char) * bytes);
94   text->buffer = (unicode_char *)osd_malloc_array(sizeof(unicode_char) * columns);
9595   if (!text->buffer)
9696   {
9797      osd_free(text);
r26376r26377
108108   }
109109
110110   /* initialize the buffer description */
111   text->bufsize = bytes;
111   text->bufsize = columns;
112112   text->linesize = lines;
113113   text_buffer_clear(text);
114114
r26376r26377
183183   INT32 needed_space;
184184
185185   /* we need to ensure there is enough space for this string plus enough for the max line length */
186   needed_space = utf8_ucharlen(data) + MAX_LINE_LENGTH;
186   needed_space = utf8_width(data) + MAX_LINE_LENGTH;
187187
188188   /* make space in the buffer if we need to */
189189   while (buffer_space(text) < needed_space && text->linestart != text->lineend)
r26376r26377
194194      text->bufstart = text->lineoffs[text->linestart];
195195   }
196196
197   size_t avail = strlen(data);
197198   /* now add the data */
198199   while (*data)
199200   {
200      unicode_char ch;
201      unicode_char uchar;
201202      int linelen;
202      int utf8len = uchar_from_utf8(&ch, data, strlen(data));
203      if (utf8len > 0)
204         data += utf8len;
203      int utf8len = uchar_from_utf8(&uchar, data, avail);
204      if (utf8len < 0)
205         break;
206      data += utf8len;
207      avail -= utf8len;
205208
206209      /* a CR resets our position */
207      if (ch == '\r')
210      if (uchar == '\r')
208211         text->bufend = text->lineoffs[text->lineend];
209212
210213      /* non-CR data is just characters */
211      else if (ch != '\n')
212         text->buffer[text->bufend++] = ch;
214      else if (uchar != '\n')
215         text->buffer[text->bufend++] = uchar;
213216
214217      /* an explicit newline or line-too-long condition inserts a newline */
215218      linelen = text->bufend - text->lineoffs[text->lineend];
216      if (ch == '\n' || linelen >= stopcol)
219      if (uchar == '\n' || linelen >= stopcol)
217220      {
218221         int overflow = 0;
219222
branches/alto2/src/emu/debug/dvtext.h
r26376r26377
22// copyright-holders:Aaron Giles
33/*********************************************************************
44
5    dvtext.h
5   dvtext.h
66
7    Debugger simple text-based views.
7   Debugger simple text-based views.
88
99***************************************************************************/
1010
r26376r26377
3636
3737private:
3838   // internal state
39   text_buffer &       m_textbuf;              /* pointer to the text buffer */
39   text_buffer &       m_textbuf;                  /* reference to the text buffer */
4040   bool                m_at_bottom;                /* are we tracking new stuff being added? */
4141   UINT32              m_topseq;                   /* sequence number of the top line */
4242};
branches/alto2/src/emu/debug/textbuf.h
r26376r26377
2727***************************************************************************/
2828
2929/* allocate a new text buffer */
30text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines);
30text_buffer *text_buffer_alloc(UINT32 columns, UINT32 lines);
3131
3232/* free a text buffer */
3333void text_buffer_free(text_buffer *text);
branches/alto2/src/lib/util/unicode.c
r26376r26377
2121 */
2222int uchar_isvalid(unicode_char uchar)
2323{
24    return (uchar < 0x110000) && !((uchar >= 0xd800) && (uchar <= 0xdfff));
24   return (uchar < 0x110000) && !((uchar >= 0xd800) && (uchar <= 0xdfff));
2525}
2626
2727
r26376r26377
324324 * @param plen optional pointer to a size_t variable to receive the source string length
325325 * @return number of unicode_char values decoded from the UTF-8 string
326326 */
327size_t utf8_ucharlen(const char* utf8src, size_t * plen)
327size_t utf8_width(const char* utf8src, size_t * plen)
328328{
329329   size_t len = 0;
330330   size_t total = 0;
r26376r26377
393393 * @param plen optional pointer to a size_t variable to receive the source string length
394394 * @return number of unicode_char values decoded from the UTF-8 string
395395 */
396size_t utf16_ucharlen(const utf16_char* utf16src, size_t * plen)
396size_t utf16_width(const utf16_char* utf16src, size_t * plen)
397397{
398398   size_t len = 0;
399399   size_t total = 0;
r26376r26377
534534}
535535
536536/**
537 * @brief return an unicode_char array allocated while converted from UTF-8
537 * @brief fill an unicode_char array with values decoded from UTF-8
538 * @param ustr destination unicode_char string
539 * @param size maximum size ucharstr array in unicode_char
538540 * @param utf8char source string encoded in UTF-8
539 * @return newly allocated unicode_char string
541 * @return number of unicode_char decoded excluding the final 0, or -1 on error
540542 */
541unicode_char* uchar_strfrom_utf8(const char *utf8src)
543size_t ustring_from_utf8(unicode_char* ustr, size_t size, const char *utf8src)
542544{
543   size_t available;
544   size_t size = utf8_ucharlen(utf8src, &available);
545   if (-1 == size)
546      return NULL;
547   unicode_char* result = (unicode_char *)calloc(sizeof(unicode_char), size + 1);
548   unicode_char* dst = result;
549   while (*utf8src) {
550      unicode_char uchar = 0;
551      int len = uchar_from_utf8(&uchar, utf8src, available);
545   size_t avail;
546   size_t width = utf8_width(utf8src, &avail);
547   if (-1 == width)
548      return width;
549   size_t length;
550   for (length = 0; *utf8src && length < size - 1; length++)
551   {
552      int len = uchar_from_utf8(&ustr[length], utf8src, avail);
553      if (len < 0)
554         break;
552555      utf8src += len;
553      available -= len;
554      *dst++ = uchar;
556      avail -= len;
555557   }
556   return result;
558   ustr[length] = 0;
559   return length;
557560}
558561
559562/**
560563 * @brief return an unicode_char array allocated while converted from UTF-16
561 * @param utf16src source string encoded in UTF-16
562 * @return newly allocated unicode_char string
564 * @param ustr destination unicode_char string
565 * @param size maximum size ucharstr array in unicode_char
566 * @param utf16char source string encoded in UTF-16
567 * @return number of unicode_char decoded excluding the final 0, or -1 on error
563568 */
564unicode_char* uchar_strfrom_utf16(const utf16_char *utf16src)
569size_t ustring_from_utf16(unicode_char* ustr, size_t size, const utf16_char *utf16src)
565570{
566   size_t available;
567   size_t size = utf16_ucharlen(utf16src, &available);
568   if (-1 == size)
569      return NULL;
570   unicode_char* result = (unicode_char *)calloc(sizeof(unicode_char), size + 1);
571   unicode_char* dst = result;
572   while (*utf16src) {
573      unicode_char uchar = 0;
574      int len = uchar_from_utf16(&uchar, utf16src, available);
571   size_t avail;
572   size_t width = utf16_width(utf16src, &avail);
573   if (-1 == width)
574      return width;
575   size_t length;
576   for (length = 0; *utf16src && length < size - 1; length++)
577   {
578      int len = uchar_from_utf16(&ustr[length], utf16src, avail);
579      if (len < 0)
580         break;
575581      utf16src += len;
576      available -= len;
577      *dst++ = uchar;
582      avail -= len;
578583   }
579   return result;
584   ustr[length] = 0;
585   return length;
580586}
581587
582588/**
r26376r26377
636642 * @param format format string followed by optional parameters
637643 * @return number of unicode_char stored in dst
638644 */
639int uchar_sprintf(unicode_char* dst, const char* format, ...)
645int uchar_sprintf(unicode_char* ustr, const char* format, ...)
640646{
641647   va_list ap;
642648   char buff[256];
r26376r26377
644650   int len = vsnprintf(buff, sizeof(buff), format, ap);
645651   va_end(ap);
646652   for (int i = 0; i < len; i++)
647      *dst++ = buff[i];
648   *dst = 0;
653      *ustr++ = buff[i];
654   *ustr = 0;
649655   return len;
650656}
651657
652658/**
659 * @brief print a formatted string of ASCII characters to an unicode_char array
660 * @param dst pointer to the array
661 * @param format format string followed by optional parameters
662 * @param size maximum number of unicode_char to write to dst
663 * @return number of unicode_char stored in dst
664 */
665int uchar_snprintf(unicode_char* ustr, size_t size, const char* format, ...)
666{
667   va_list ap;
668   char buff[256];
669   va_start(ap, format);
670   int len = vsnprintf(buff, sizeof(buff), format, ap);
671   va_end(ap);
672   if (len < 0)
673      return len;
674   for (int i = 0; i < len; i++)
675      *ustr++ = buff[i];
676   *ustr = 0;
677   return len;
678}
679
680/**
653681 * @brief copy an array of unicode_char from source to destination
654682 *
655683 * @param dst pointer to destination array
branches/alto2/src/lib/util/unicode.h
r26376r26377
145145//! convert an unicode character into a UTF-16 sequence with flipped endianness
146146int utf16f_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar);
147147
148//! return the number of decoded Unicode values in UTF-8 encoded string
149size_t utf8_ucharlen(const char* utf8src, size_t * plen = 0);
148//! return the width of an UTF-8 encoded string (number of decoded Unicode glyphs)
149size_t utf8_width(const char* utf8src, size_t * plen = 0);
150150
151//! return the number of decoded Unicode values in UTF-16 encoded string
152size_t utf16_ucharlen(const utf16_char* utf16src, size_t * plen = 0);
151//! return the width of an UTF-16 encoded string (number of decoded Unicode glyphs)
152size_t utf16_width(const utf16_char* utf16src, size_t * plen = 0);
153153
154154/* misc UTF-8 helpers */
155155//! return a pointer to the previous character in a string
r26376r26377
168168//! free a unicode table
169169void uchar_table_free(unicode_char* table);
170170
171//! return an unicode_char array allocated while converted from UTF-8
172unicode_char* ustring_from_utf8(const char *utf8char);
171//! fill an unicode_char array with values decoded from UTF-8
172size_t ustring_from_utf8(unicode_char* ucharstr, size_t max, const char *utf8char);
173173
174//! return an unicode_char array allocated while converted from UTF-16
175unicode_char* ustring_from_utf16(const utf16_char *utf16char);
174//! fill an unicode_char array with values decoded from UTF-16
175size_t ustring_from_utf16(unicode_char* ucharstr, size_t max, const utf16_char *utf16char);
176176
177177/* unicode_char array functions - string.h like */
178178//! return the unicode_char array length
r26376r26377
185185int uchar_strncmp(const unicode_char* dst, const unicode_char* src, size_t len);
186186
187187//! print a formatted string of ASCII characters to an unicode_char array (max 256 characters)
188int uchar_sprintf(unicode_char* dst, const char* format, ...);
188int uchar_sprintf(unicode_char* ustr, const char* format, ...);
189189
190190//! print a formatted string of ASCII characters to an unicode_char array (max size characters)
191int uchar_snprintf(unicode_char* dst, size_t size, const char* format, ...);
191int uchar_snprintf(unicode_char* ustr, size_t size, const char* format, ...);
192192
193193//! copy an array of unicode_char from source to destination
194194unicode_char* uchar_strcpy(unicode_char* dst, const unicode_char* src);

Previous 199869 Revisions Next


© 1997-2024 The MAME Team