From eae75824d3c8d697216a9782b9f7ca6494ef431d Mon Sep 17 00:00:00 2001 From: wilbertpol Date: Tue, 5 Oct 2021 19:16:42 +0200 Subject: [PATCH] =?UTF-8?q?softlist.cpp:=20Add=20support=20for=20a=20'note?= =?UTF-8?q?s'=20field=20to=20store=20information=20ab=E2=80=A6=20(#8482)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * softlist.cpp: Add support for a 'notes' field to store information about a software list or software list item. [Wilbert Pol] * Add software list and software notes to minimaws --- hash/softwarelist.dtd | 5 +- hash/wswan.xml | 88 +++++++++++++++---------------- scripts/minimaws/lib/dbaccess.py | 18 +++++-- scripts/minimaws/lib/htmltmpl.py | 8 +++ scripts/minimaws/lib/lxparse.py | 20 +++++-- scripts/minimaws/lib/wsgiserve.py | 6 +++ src/emu/softlist.cpp | 31 ++++++++++- src/emu/softlist.h | 3 ++ src/emu/softlist_dev.cpp | 6 ++- src/emu/softlist_dev.h | 2 + src/frontend/mame/clifront.cpp | 10 +++- 11 files changed, 138 insertions(+), 59 deletions(-) diff --git a/hash/softwarelist.dtd b/hash/softwarelist.dtd index ce3541c7d0d..946a562d94f 100644 --- a/hash/softwarelist.dtd +++ b/hash/softwarelist.dtd @@ -1,7 +1,8 @@ - + - + + diff --git a/hash/wswan.xml b/hash/wswan.xml index 932bb4e0b2e..a9932da2e0a 100644 --- a/hash/wswan.xml +++ b/hash/wswan.xml @@ -2,7 +2,9 @@ + + - - +]]> Anchorz Field 1999 @@ -523,10 +523,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Chou Aniki - Otoko no Tamafuda 2000 Bandai + Revision from header: Rev 4 @@ -546,10 +546,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Chou Denki Card Game - Youfu Makai - Kikuchi Shuukou 1999 Kobunsha + Revision from header: Rev 3 @@ -569,10 +569,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Clock Tower for WonderSwan 1999 Kaga Tech + Revision from header: Rev 1 @@ -611,10 +611,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Densha de Go! 1999 Taito + Revision from header: Rev 1 @@ -762,12 +762,11 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. --> - - Digital Monster - Ver. WonderSwan 1999 Bandai + Revision from header: Rev 1 @@ -787,7 +786,6 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Digimon - Ver. WonderSwan (Asia) 19?? Bandai @@ -980,10 +978,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Fire Pro Wrestling for WonderSwan 2000 Kaga Tech + Revision from header: Rev 5 @@ -1063,10 +1061,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Goraku Ou Tango! 1999 Moebius + Revision from header: Rev 2 @@ -1186,11 +1184,11 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Harobots (Rev 1) 1999 Sunrise Interactive + background incorrect during bot transform? @@ -1339,10 +1337,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Kiss Yori... - Seaside Serenade 1999 Kid + Revision from header: Rev 2 @@ -1406,10 +1404,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Kyousouba Ikusei Simulation - Keiba 1999 BEC + Revision from header: Rev 1 @@ -1429,10 +1427,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Langrisser Millennium WS - The Last Century 2000 Bandai + Revision from header: Rev 1 @@ -1516,11 +1514,11 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Magical Drop for WonderSwan 1999 Data East Corp. + Small graphics glitch between 4th and 5th column @@ -1691,10 +1689,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Mingle Magnet 1999 Hal Corporation + Revision from header: Rev 1 @@ -1711,10 +1709,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Pro Mahjong Kiwame for WonderSwan 1999 Athena + Revision from header: Rev 1 @@ -1734,10 +1732,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Nihon Pro Mahjong Renmei Kounin Tetsuman 1999 Kaga Tech + Revision from header: Rev 2 @@ -1756,12 +1754,11 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - - MobileWonderGate (Rev 1) 19?? <unknown> + wondergate hardware is not emulated yet @@ -1866,10 +1863,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Nice On 1999 Sammy + Revision from header: Rev 1 @@ -2060,6 +2057,7 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. Ring Infinity (alt) 2000 Kid + The roms in this are a simple split of mh32m16e119b.u3. It needs to be verified whether this is correct. @@ -2071,7 +2069,6 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - @@ -2212,15 +2209,15 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Wonder Borg Robot Works 2000 Bandai + @@ -2240,17 +2237,20 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - - Robot Works (Asia) 2000 Bandai - + + @@ -2506,10 +2506,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Shin Nihon Pro Wrestling Toukon Retsuden 1999 Tomy + Revision from header: Rev 1 @@ -2609,10 +2609,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Sotsugyou for WonderSwan 1999 Bandai Visual + Revision from header: Rev 1 @@ -2695,10 +2695,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Tanjou Debut for WonderSwan 2000 Bandai Visual + Revision from header: Rev 1 @@ -2848,10 +2848,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Trump Collection 2 - Bottom-Up Teki Sekaiisshuu no Tabi 2000 Bottom Up + Revision from header: Rev 1 @@ -2868,10 +2868,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Trump Collection - Bottom-Up Teki Trump Seikatsu 1999 Bottom Up + Revision from header: Rev 1 @@ -2928,10 +2928,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Uzumaki - Denshi Kaiki Hen 2000 Omage Micott, Inc. + Revision from header: Rev 4 @@ -2950,10 +2950,10 @@ The GIZA chip used on a lot of cartridges is a sram voltage switch. - Vaitz Blade 1999 Bandai + Revision from header: Rev 1 diff --git a/scripts/minimaws/lib/dbaccess.py b/scripts/minimaws/lib/dbaccess.py index c22b7c318fa..208b22a02c7 100644 --- a/scripts/minimaws/lib/dbaccess.py +++ b/scripts/minimaws/lib/dbaccess.py @@ -32,6 +32,7 @@ class SchemaQueries(object): ' id INTEGER PRIMARY KEY,\n' \ ' shortname TEXT NOT NULL,\n' \ ' description TEXT NOT NULL,\n' \ + ' notes TEXT NULL,\n' \ ' UNIQUE (shortname ASC))' CREATE_SOFTWARE = \ 'CREATE TABLE software (\n' \ @@ -42,6 +43,7 @@ class SchemaQueries(object): ' description TEXT NOT NULL,\n' \ ' year TEXT NOT NULL,\n' \ ' publisher TEXT NOT NULL,\n' \ + ' notes TEXT NULL,\n' \ ' UNIQUE (softwarelist ASC, shortname ASC),\n' \ ' FOREIGN KEY (softwarelist) REFERENCES softwarelist (id))' CREATE_SOFTWARECLONEOF = \ @@ -505,6 +507,8 @@ class UpdateQueries(object): ADD_SOFTWARESHAREDFEAT = 'INSERT INTO softwaresharedfeat (software, sharedfeattype, value) SELECT ?, id, ? FROM softwaresharedfeattype WHERE name = ?' ADD_SOFTWAREPART = 'INSERT INTO softwarepart (software, shortname, interface) VALUES (?, ?, ?)' ADD_SOFTWAREPARTFEATURE = 'INSERT INTO softwarepartfeature (part, featuretype, value) SELECT ?, id, ? FROM softwarepartfeaturetype WHERE name = ?' + UPDATE_SOFTWARELIST_NOTES = 'UPDATE softwarelist SET notes = ? WHERE id = ?' + UPDATE_SOFTWARE_NOTES = 'UPDATE software SET notes = ? WHERE id = ?' # machines ADD_FEATURETYPE = 'INSERT OR IGNORE INTO featuretype (name) VALUES (?)' @@ -773,7 +777,7 @@ class QueryCursor(object): def get_machine_softwarelists(self, machine): return self.dbcurs.execute( - 'SELECT machinesoftwarelist.tag AS tag, machinesoftwareliststatustype.value AS status, softwarelist.shortname AS shortname, softwarelist.description AS description, COUNT(software.id) AS total, COUNT(CASE software.supported WHEN 0 THEN 1 ELSE NULL END) AS supported, COUNT(CASE software.supported WHEN 1 THEN 1 ELSE NULL END) AS partiallysupported, COUNT(CASE software.supported WHEN 2 THEN 1 ELSE NULL END) AS unsupported ' \ + 'SELECT machinesoftwarelist.tag AS tag, machinesoftwareliststatustype.value AS status, softwarelist.shortname AS shortname, softwarelist.description AS description, softwarelist.notes AS notes, COUNT(software.id) AS total, COUNT(CASE software.supported WHEN 0 THEN 1 ELSE NULL END) AS supported, COUNT(CASE software.supported WHEN 1 THEN 1 ELSE NULL END) AS partiallysupported, COUNT(CASE software.supported WHEN 2 THEN 1 ELSE NULL END) AS unsupported ' \ 'FROM machinesoftwarelist LEFT JOIN machinesoftwareliststatustype ON machinesoftwarelist.status = machinesoftwareliststatustype.id LEFT JOIN softwarelist ON machinesoftwarelist.softwarelist = softwarelist.id LEFT JOIN software ON softwarelist.id = software.softwarelist ' \ 'WHERE machinesoftwarelist.machine = ? ' \ 'GROUP BY machinesoftwarelist.id', @@ -785,14 +789,14 @@ class QueryCursor(object): def get_softwarelist_details(self, shortname, pattern): if pattern is not None: return self.dbcurs.execute( - 'SELECT softwarelist.id AS id, softwarelist.shortname AS shortname, softwarelist.description AS description, COUNT(software.id) AS total, COUNT(CASE software.supported WHEN 0 THEN 1 ELSE NULL END) AS supported, COUNT(CASE software.supported WHEN 1 THEN 1 ELSE NULL END) AS partiallysupported, COUNT(CASE software.supported WHEN 2 THEN 1 ELSE NULL END) AS unsupported ' \ + 'SELECT softwarelist.id AS id, softwarelist.shortname AS shortname, softwarelist.description AS description, softwarelist.notes AS notes, COUNT(software.id) AS total, COUNT(CASE software.supported WHEN 0 THEN 1 ELSE NULL END) AS supported, COUNT(CASE software.supported WHEN 1 THEN 1 ELSE NULL END) AS partiallysupported, COUNT(CASE software.supported WHEN 2 THEN 1 ELSE NULL END) AS unsupported ' \ 'FROM softwarelist LEFT JOIN software ON softwarelist.id = software.softwarelist ' \ 'WHERE softwarelist.shortname = ? AND software.shortname GLOB ? ' \ 'GROUP BY softwarelist.id', (shortname, pattern)) else: return self.dbcurs.execute( - 'SELECT softwarelist.id AS id, softwarelist.shortname AS shortname, softwarelist.description AS description, COUNT(software.id) AS total, COUNT(CASE software.supported WHEN 0 THEN 1 ELSE NULL END) AS supported, COUNT(CASE software.supported WHEN 1 THEN 1 ELSE NULL END) AS partiallysupported, COUNT(CASE software.supported WHEN 2 THEN 1 ELSE NULL END) AS unsupported ' \ + 'SELECT softwarelist.id AS id, softwarelist.shortname AS shortname, softwarelist.description AS description, softwarelist.notes AS notes, COUNT(software.id) AS total, COUNT(CASE software.supported WHEN 0 THEN 1 ELSE NULL END) AS supported, COUNT(CASE software.supported WHEN 1 THEN 1 ELSE NULL END) AS partiallysupported, COUNT(CASE software.supported WHEN 2 THEN 1 ELSE NULL END) AS unsupported ' \ 'FROM softwarelist LEFT JOIN software ON softwarelist.id = software.softwarelist ' \ 'WHERE softwarelist.shortname = ? ' \ 'GROUP BY softwarelist.id', @@ -836,7 +840,7 @@ class QueryCursor(object): def get_software_details(self, softwarelist, software): return self.dbcurs.execute( - 'SELECT software.id AS id, software.shortname AS shortname, software.supported AS supported, software.description AS description, software.year AS year, software.publisher AS publisher, softwarelist.shortname AS softwarelist, softwarelist.description AS softwarelistdescription, parent.shortname AS parent, parent.description AS parentdescription, parentsoftwarelist.shortname AS parentsoftwarelist, parentsoftwarelist.description AS parentsoftwarelistdescription ' \ + 'SELECT software.id AS id, software.shortname AS shortname, software.supported AS supported, software.description AS description, software.year AS year, software.publisher AS publisher, software.notes AS notes, softwarelist.shortname AS softwarelist, softwarelist.description AS softwarelistdescription, parent.shortname AS parent, parent.description AS parentdescription, parentsoftwarelist.shortname AS parentsoftwarelist, parentsoftwarelist.description AS parentsoftwarelistdescription ' \ 'FROM software LEFT JOIN softwarelist ON software.softwarelist = softwarelist.id LEFT JOIN softwarecloneof ON software.id = softwarecloneof.id LEFT JOIN software AS parent ON softwarecloneof.parent = parent.id LEFT JOIN softwarelist AS parentsoftwarelist ON parent.softwarelist = parentsoftwarelist.id ' \ 'WHERE software.softwarelist = (SELECT id FROM softwarelist WHERE shortname = ?) AND software.shortname = ?', (softwarelist, software)) @@ -912,6 +916,9 @@ class UpdateCursor(object): self.dbcurs.execute(UpdateQueries.ADD_SOFTWARELIST, (shortname, description)) return self.dbcurs.lastrowid + def update_softwarelist_notes(self, id, notes): + self.dbcurs.execute(UpdateQueries.UPDATE_SOFTWARELIST_NOTES, (notes, id)) + def add_softwareinfotype(self, name): self.dbcurs.execute(UpdateQueries.ADD_SOFTWAREINFOTYPE, (name, )) @@ -925,6 +932,9 @@ class UpdateCursor(object): self.dbcurs.execute(UpdateQueries.ADD_SOFTWARE, (softwarelist, shortname, supported, description, year, publisher)) return self.dbcurs.lastrowid + def update_software_notes(self, id, notes): + self.dbcurs.execute(UpdateQueries.UPDATE_SOFTWARE_NOTES, (notes, id)) + def add_softwarecloneof(self, software, parent): self.dbcurs.execute(UpdateQueries.ADD_TEMPORARY_SOFTWARECLONEOF, (software, parent)) return self.dbcurs.lastrowid diff --git a/scripts/minimaws/lib/htmltmpl.py b/scripts/minimaws/lib/htmltmpl.py index a80b4099787..4f3bf12bb46 100644 --- a/scripts/minimaws/lib/htmltmpl.py +++ b/scripts/minimaws/lib/htmltmpl.py @@ -258,6 +258,10 @@ SOFTWARE_PROLOGUE = string.Template( ' Year:${year}\n' \ ' Publisher:${publisher}\n'); +SOFTWARE_EPILOGUE = string.Template( + '

Notes

\n' \ + '

${notes}

\n'); + SOFTWARE_CLONES_PROLOGUE = string.Template( '

Clones

\n' \ '\n' \ @@ -328,6 +332,10 @@ SOFTWARELIST_PROLOGUE = string.Template( ' \n' \ '
\n') +SOFTWARELIST_EPILOGUE = string.Template( + '

Notes

\n' \ + '

${notes}

\n') + SOFTWARELIST_MACHINE_TABLE_HEADER = string.Template( '

Machines

\n' \ '\n' \ diff --git a/scripts/minimaws/lib/lxparse.py b/scripts/minimaws/lib/lxparse.py index 46737ef438a..699695577fc 100644 --- a/scripts/minimaws/lib/lxparse.py +++ b/scripts/minimaws/lib/lxparse.py @@ -352,6 +352,7 @@ class SoftwareHandler(ElementHandler): 'description': TextAccumulator, 'year': TextAccumulator, 'publisher': TextAccumulator, + 'notes': TextAccumulator, 'part': SoftwarePartHandler } def __init__(self, parent, **kwargs): @@ -389,6 +390,9 @@ class SoftwareHandler(ElementHandler): self.id = self.dbcurs.add_software(self.softwarelist, self.shortname, self.supported, self.description, self.year, self.publisher) if self.cloneof is not None: self.dbcurs.add_softwarecloneof(self.id, self.cloneof) + elif name == 'notes': + self.notes = handler.text + self.dbcurs.update_software_notes(self.id, self.notes) class SoftwareListHandler(ElementHandler): @@ -410,24 +414,34 @@ class SoftwareListHandler(ElementHandler): locator=self.locator) self.shortname = attrs['name'] self.description = attrs['description'] + self.notes = None self.entries = 0 dbcurs = self.dbconn.cursor() self.id = dbcurs.add_softwarelist(self.shortname, self.description) dbcurs.close() def endMainElement(self, name): + if self.notes: + dbcurs = self.dbconn.cursor() + dbcurs.update_softwarelist_notes(self.id, self.notes) + dbcurs.close() self.dbconn.commit() def startChildElement(self, name, attrs): - if name != 'software': + if name == 'notes': + self.setChildHandler(name, attrs, TextAccumulator(self)) + elif name == 'software': + self.setChildHandler(name, attrs, SoftwareHandler(self)) + else: raise xml.sax.SAXParseException( msg=('Expected "software" element but found "%s"' % (name, )), exception=None, locator=self.locator) - self.setChildHandler(name, attrs, SoftwareHandler(self)) def endChildHandler(self, name, handler): - if name == 'software': + if name == 'notes': + self.notes = handler.text + elif name == 'software': if self.entries >= 1023: self.dbconn.commit() self.entries = 0 diff --git a/scripts/minimaws/lib/wsgiserve.py b/scripts/minimaws/lib/wsgiserve.py index 43d5dbc1253..3b92f08110d 100644 --- a/scripts/minimaws/lib/wsgiserve.py +++ b/scripts/minimaws/lib/wsgiserve.py @@ -689,6 +689,9 @@ class SoftwareListHandler(QueryPageHandler): yield htmltmpl.SORTABLE_TABLE_EPILOGUE.substitute(id='tbl-software').encode('utf-8') yield '\n'.encode('utf-8') + if (softwarelist_info['notes']): + yield htmltmpl.SOFTWARELIST_EPILOGUE.substitute(notes=htmlescape(softwarelist_info['notes'])).encode('utf-8') + yield '\n\n'.encode('utf-8') def software_page(self, software_info): @@ -733,6 +736,9 @@ class SoftwareListHandler(QueryPageHandler): yield (' \n' % (htmlescape(name), htmlescape(value))).encode('utf-8') yield '
%s:%s
\n\n'.encode('utf-8') + if (software_info['notes']): + yield htmltmpl.SOFTWARE_EPILOGUE.substitute(notes=htmlescape(software_info['notes'])).encode('utf-8') + yield '\n\n'.encode('utf-8') def software_row(self, software_info): diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp index 34517aa13ce..8ee8d0d8500 100644 --- a/src/emu/softlist.cpp +++ b/src/emu/softlist.cpp @@ -196,6 +196,7 @@ public: std::string_view filename, std::string &listname, std::string &description, + std::string ¬es, std::list &infolist, std::ostream &errors); @@ -236,6 +237,7 @@ private: void parse_soft_start(const char *tagname, const char **attributes); void parse_part_start(const char *tagname, const char **attributes); void parse_data_start(const char *tagname, const char **attributes); + void parse_main_end(const char *tagname); void parse_soft_end(const char *name); // internal parsing state @@ -245,6 +247,7 @@ private: struct XML_ParserStruct * m_parser; std::string & m_listname; std::string & m_description; + std::string & m_notes; bool m_data_accum_expected; std::string m_data_accum; software_info * m_current_info; @@ -262,6 +265,7 @@ softlist_parser::softlist_parser( std::string_view filename, std::string &listname, std::string &description, + std::string ¬es, std::list &infolist, std::ostream &errors) : m_filename(filename), @@ -269,6 +273,7 @@ softlist_parser::softlist_parser( m_errors(errors), m_listname(listname), m_description(description), + m_notes(notes), m_data_accum_expected(false), m_current_info(nullptr), m_current_part(nullptr), @@ -472,6 +477,7 @@ void softlist_parser::end_handler(void *data, const char *name) break; case POS_MAIN: + state->parse_main_end(name); state->m_current_info = nullptr; break; @@ -563,13 +569,25 @@ void softlist_parser::parse_main_start(const char *tagname, const char **attribu else parse_error("No name defined for item"); } + // + else if (strcmp(tagname, "notes") == 0) + { + m_data_accum_expected = true; + } else unknown_tag(tagname); } +void softlist_parser::parse_main_end(const char *tagname) +{ + if (strcmp(tagname, "notes") == 0) + m_notes = m_data_accum; +} + + //------------------------------------------------- -// parse_main_start - handle tag start within +// parse_soft_start - handle tag start within // a software tag //------------------------------------------------- @@ -594,6 +612,10 @@ void softlist_parser::parse_soft_start(const char *tagname, const char **attribu else if (strcmp(tagname, "publisher") == 0) m_data_accum_expected = true; + // + else if (strcmp(tagname, "notes") == 0) + m_data_accum_expected = true; + // else if (strcmp(tagname, "info") == 0) { @@ -859,6 +881,10 @@ void softlist_parser::parse_soft_end(const char *tagname) else if (strcmp(tagname, "publisher") == 0) m_current_info->m_publisher = m_data_accum; + // + else if (strcmp(tagname, "notes") == 0) + m_current_info->m_notes = m_data_accum; + // else if (strcmp(tagname, "part") == 0) { @@ -887,10 +913,11 @@ void parse_software_list( std::string_view filename, std::string &listname, std::string &description, + std::string ¬es, std::list &infolist, std::ostream &errors) { - detail::softlist_parser(file, filename, listname, description, infolist, errors); + detail::softlist_parser(file, filename, listname, description, notes, infolist, errors); } diff --git a/src/emu/softlist.h b/src/emu/softlist.h index 7622e7e00d1..2c7a4e545dd 100644 --- a/src/emu/softlist.h +++ b/src/emu/softlist.h @@ -120,6 +120,7 @@ public: const std::string &parentname() const { return m_parentname; } const std::string &year() const { return m_year; } const std::string &publisher() const { return m_publisher; } + const std::string ¬es() const { return m_notes; } const std::list &other_info() const { return m_other_info; } const std::list &shared_info() const { return m_shared_info; } software_support supported() const { return m_supported; } @@ -137,6 +138,7 @@ private: std::string m_parentname; std::string m_year; // Copyright year on title screen, actual release dates can be tracked in external resources std::string m_publisher; + std::string m_notes; std::list m_other_info; // Here we store info like developer, serial #, etc. which belong to the software entry as a whole std::list m_shared_info; // Here we store info like TV standard compatibility, or add-on requirements, etc. which get inherited // by each part of this software entry (after loading these are stored in partdata->featurelist) @@ -152,6 +154,7 @@ void parse_software_list( std::string_view filename, std::string &listname, std::string &description, + std::string ¬es, std::list &infolist, std::ostream &errors); diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp index 7d25dd17013..7d7e1930089 100644 --- a/src/emu/softlist_dev.cpp +++ b/src/emu/softlist_dev.cpp @@ -89,7 +89,8 @@ software_list_device::software_list_device(const machine_config &mconfig, const m_list_type(softlist_type::ORIGINAL_SYSTEM), m_filter(nullptr), m_parsed(false), - m_description("") + m_description(""), + m_notes("") { } @@ -180,6 +181,7 @@ void software_list_device::release() m_filename.clear(); m_shortname.clear(); m_description.clear(); + m_notes.clear(); m_errors.clear(); m_infolist.clear(); } @@ -294,7 +296,7 @@ void software_list_device::parse() { // parse if no error std::ostringstream errs; - parse_software_list(file, m_filename, m_shortname, m_description, m_infolist, errs); + parse_software_list(file, m_filename, m_shortname, m_description, m_notes, m_infolist, errs); file.close(); m_errors = errs.str(); } diff --git a/src/emu/softlist_dev.h b/src/emu/softlist_dev.h index e0e912a67f1..2de72bd3b8f 100644 --- a/src/emu/softlist_dev.h +++ b/src/emu/softlist_dev.h @@ -116,6 +116,7 @@ public: // getters that may trigger a parse const std::string &description() { if (!m_parsed) parse(); return m_description; } + const std::string ¬es() { if (!m_parsed) parse(); return m_notes; } bool valid() { if (!m_parsed) parse(); return !m_infolist.empty(); } const char *errors_string() { if (!m_parsed) parse(); return m_errors.c_str(); } const std::list &get_info() { if (!m_parsed) parse(); return m_infolist; } @@ -152,6 +153,7 @@ private: std::string m_filename; std::string m_shortname; std::string m_description; + std::string m_notes; std::string m_errors; std::list m_infolist; }; diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index eb77ead8e5c..bc78cb1112c 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -1059,16 +1059,18 @@ const char cli_frontend::s_softlist_xml_dtd[] = "\n" \ "\n" \ - "\t\n" \ + "\t\n" \ "\t\t\n" \ "\t\t\n" \ - "\t\t\n" \ + "\t\t\n" \ + "\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\n" \ + "\t\t\t\n" \ "\t\t\t\n" \ "\t\t\t\t\n" \ "\t\t\t\t\n" \ @@ -1116,6 +1118,8 @@ const char cli_frontend::s_softlist_xml_dtd[] = void cli_frontend::output_single_softlist(std::ostream &out, software_list_device &swlistdev) { util::stream_format(out, "\t\n", swlistdev.list_name(), util::xml::normalize_string(swlistdev.description().c_str())); + if (!swlistdev.notes().empty()) + util::stream_format(out, "\t\t%s\n", util::xml::normalize_string(swlistdev.notes().c_str())); for (const software_info &swinfo : swlistdev.get_info()) { util::stream_format(out, "\t\t%s\n", util::xml::normalize_string(swinfo.longname().c_str())); util::stream_format(out, "\t\t\t%s\n", util::xml::normalize_string(swinfo.year().c_str())); util::stream_format(out, "\t\t\t%s\n", util::xml::normalize_string(swinfo.publisher().c_str())); + if (!swinfo.notes().empty()) + util::stream_format(out, "\t\t\t%s\n", util::xml::normalize_string(swinfo.notes().c_str())); for (const feature_list_item &flist : swinfo.other_info()) util::stream_format(out, "\t\t\t\n", flist.name(), util::xml::normalize_string(flist.value().c_str()));