Новая реальность - информационный игровой портал

XMDB

Формат данных XMDB используется утилитой GoodMerge для более эффективного сжатия образов игр. GoodMerge изначально разрабатывалась в качестве компаньона к утилитам GoodTools, но в настоящее время стало возможным так же генерировать XMDB файлы на основе колекций No-Intro.

Идея очень проста — схожие файлы группируются, и результирующий архив, если говорить достаточно грубо, хранит только разницу между ними, а разница может быть всего несколько байт. В результате, размер архива складывается из размера сжатого ROM'a + размер упакованной разницы, что, повторюсь ещё раз, сильно экономит место.

Перво-наперво, давайте рассмотрим структуру XML документа:

 <!--
 no-intro | www.no-intro.org | 20161023-053252
 -->
 <romsets>
    <set name="REQUIRED" version="REQUIRED">
         Nintendo - Family Computer Disk System 
        <options>
            <ext text="REQUIRED"></ext>
            <flag reg="REQUIRED"></flag>
            <hackflag reg="REQUIRED"></hackflag>
            <ignore reg="REQUIRED"></ignore>
        </options>
        <parents>
             Hacks, Versions, etc." 
            <parent name="REQUIRED">
                <clone name="REQUIRED"></clone>
                <group reg="REQUIRED"></group>
            </parent>
             Biased 
            <zoned type="normal|deferred">
                <bias zone="REQUIRED" name="REQUIRED"></bias>
                <clone></clone>
                <group></group>
            </zoned>
        </parents>
    </set>
 </romsets>

И «живой» вариант:

 <romsets>
 <set name="NES" version="3.23b">
     Nintendo NES/Famicom 
    <options>
        <ext text="nes"/>
        <ext text="unf"/>
        <ext text="unif"/>
        <flag reg=" (\(([ABCEFGIJKRSTUWfhsw]{0,3}(-AC|-GC)?|Unl|Russian|Tw|PAL|Asia)\)|\[)"/>
        <hackflag reg=" \("/>
        <ignore reg=" \((PC10|([A-z a-z0-9\.'!]+ )?Hack(er|-1|-2)?|VS|M[0-9]|NINA03-USA|Menu|
          (Regular|Uniform) Edition|Bootleg|Beta|Sample|Demo Cart|Debug Version|Dev version|
          Japan|Chi|Eng|Jap|FDS Conversion.*|Multicart Rip|iNES Version|GBA e-Reader|
          Prototype( V0\.0|-1|-2)?|REVA|REV1.1|REV1.x|REV2|PRG(0|1|2)|V5.0 CHR 1.3|
          V5.0 CHR 6.0|V[1-3] Plug-Thru Cart|KC|GC|(E-|J-)VC|Player [0-9] Mode|2 Joys|
          Part [0-9]|Dr\. PC Jr\.|V[0-9]\.[0-9])\)"/>
        <ignore reg=" \((CodeMasters|HES|Aladdin|Color Dreams|Tengen|Wisdom Tree|
          Camerica|Asder|Joy Van+|Hwang Shinwei|Invent|GameTec|Shin-Shin|Rex Soft|RCM Group|
          SuperGame|Mega Soft|AVE|Panesian|Bunch|AbabSoft|AGCI|Active Enterprises|
          Gluk Video(, NTDEC)?|NTDEC|Sachen(-Chinese|-English|-JAP|-USA|-HES|-FC|-Hacker|
          -Joy Van|-NTSC|-PAL|\+NINA03)?|CN-[0-9]{2}|G-[0-9]{3}|NJ[x0-9]{3}|MGC-[0-9]{3}|
          ES-[0-9]{4})\)"/>
        <ignore reg="^VS\. "/>
    </options>

Пройдёмся по этим данным:

  1. GoodMerge видит, что следует упаковывать файлы с расширениями nes, unf, unif.
  2. Элемент flag призван указать все существующие флаги (отличительные черты) игр. В случае группировки по родителям эти флаги игнорируются, а вот когда группировка идёт по зонам — эти флаги как раз и пригождаются.
  3. Элемент hackflag не очень понятен
  4. В элементе ignore мы видим аккуратно прописанные регулярные выражения — всё это должно будет проигнорировано
    при сканировании списка игр.

Дерево parents используется для группировки ROM“ов. Атрибут name это имя будущего архива, и, имя файлов для группировки. Тут есть два способа: либо напрямую прописывается имя конкретного файла (clone), либо объявляется группа group, и группировка выполняется регулярным выражением. Не запрещается использовать тот способ, который наиболее подходит, или оба одновременно.

    <parents>
        <parent name="Famista '89 - Kaimaku Han!!">
            <clone name="Famista '89 - Kaimaku Ban!!"/>
        </parent>
        <parent name="Aladdin (Unl)">
            <group reg="^Aladdin ((4|II) \(199[56]\) )?\(Unl\)"/>
            <clone name="Popeye 2 - Travels in Persia"/>
        </parent>
        <parent name="Aladdin (E)">
            <group reg="^Aladdin \(E\)"/>
        </parent>
        <parent name="Batman">
            <clone name="Batman 2004"/>
            <clone name="Batman Black"/>
            <clone name="Hell Fire"/>
        </parent>
        <parent name="Batman Returns">
            <clone name="Batman III"/>
        </parent>
        <parent name="Battle City">
            <group reg="^Battle City - "/>
            <group reg="^Battle City by"/>
            <group reg="^Battle City v4.4c"/>
            <group reg="^Future Tank"/>
            <group reg="^Missile Tank"/>
            <group reg="^PowerJoy 84-in-1 Split Game 77-Tank"/>
            <group reg="^Tank 1990 14-in-1 \[p1\]"/>
            <clone name="Battle City 2008"/>
            <clone name="Battle City APU Player by Griever"/>
            <clone name="Battle City Extreme"/>
            <clone name="Battle City LJC Edition"/>
            <clone name="Battle City Russian with Nazi Symbol by Greyson"/>
            <clone name="Battle City Stage 36-70Ghost"/>
            <clone name="Battle City Tankist"/>
            <clone name="Battle City with 6 Enemies"/>
            <clone name="Heavy Tank"/>
            <clone name="Sea War 2000"/>
            <clone name="Tank 1990"/>
        </parent>

Другой вариант группировки игр — указывать их явно, с пристрастием. Тут считается, что игры в различных зонах имеют разные названия, например:

 <zoned>
    <bias zone="U" name="Abadox - The Deadly Inner War"/>
    <bias zone="J" name="Abadox"/>
 </zoned>

Так же можно указать имена отдельных файлов без привязки к зонам. Это очень актуально для хаков:

 <zoned>
    <bias zone="En" name="Adventure Island"/>
    <bias zone="J" name="Takahashi Meijin no Bouken Shima"/>
    <clone name="Adventure Island by ssw"/>
    <clone name="Justin's Adventure Island"/>
    <clone name="Macbee's Adventure Island v3"/>
    <clone name="Sun Xiao Mao Qi Huan Dao (Kidddy Sun in Fantasia)"/>
    <clone name="Takahashi Meijin no Bouken Shima by Rinkaku"/>
    <clone name="Takahashi Meijin no Bouken Shima TT"/>
 </zoned>

И, наконец, можно даже объявить группу, как и в случае с родителями:

 <zoned>
    <bias zone="U" name="Adventure Island II"/>
    <bias zone="E" name="Adventure Island Part II, The"/>
    <bias zone="J" name="Takahashi Meijin no Bouken Shima II"/>
    <group reg="^Takahashi Meijin No Boukenjima 2 TT"/>
    <clone name="Adventure Island II Debug by dragon2snow"/>
    <clone name="Super Mario World 9"/>
 </zoned>

У zoned есть атрибут type, принимающий следующие значения: "normal", "deferred". Мне не совсем понятна разница между ними. "deferred", видимо, отменяет работу по фильтрам ingore, то есть, утилита "видит" все игнорируемые теги. Но тут я могу и ошибаться. На практике deferred используется для случаев, когда разные игры имеют одно название.

Обе структуры, zoned и parent могут чередоваться в пределах parents.

Зачем нужны оба способа, если zoned по-сути, является надмножеством parent? Я много думал над этим вопросом, и напрашиваются следующие мысли:

  1. parent не всегда позволяет однозначно сгруппировать игры. Яркий пример — Adventures of Lolo 2 — в Японии игра называется просто Adventures of Lolo, но игра с таким же названием есть и для англоязычного региона, только совершенно другая. Вот для таких случаев zoned жизненно необходим.
  2. Тем не менее, parent имеет свой плюс - он проще. Не надо указывать регион для первой игры. Но если брать коллекции No-Intro, то разработчики вообще умудряются обходиться одними zoned — структуру parent они попросту игнорируют. К тому же, наблюдается избыточность данных — расписываются сначала зоны, а потом каждый файл указывается в элементе clone.
 <zoned type="deferred">
    <bias zone="E" name="Maniac Mansion"/>
    <bias zone="F" name="Maniac Mansion"/>
    <bias zone="G" name="Maniac Mansion"/>
    <bias zone="I" name="Maniac Mansion"/>
    <bias zone="S" name="Maniac Mansion"/>
    <bias zone="Sw" name="Maniac Mansion"/>
    <bias zone="U" name="Maniac Mansion"/>
    <clone name="Maniac Mansion (Europe)"/>
    <clone name="Maniac Mansion (France)"/>
    <clone name="Maniac Mansion (Germany)"/>
    <clone name="Maniac Mansion (Italy)"/>
    <clone name="Maniac Mansion (Spain)"/>
    <clone name="Maniac Mansion (Sweden)"/>
    <clone name="Maniac Mansion (USA)"/>
    <clone name="Maniac Mansion (USA) (Beta)"/>
 </zoned>

Эту информацию можно как-то использовать.

Редакция от 22.11.2016 17:42