## AEL technical notes ##

### AEL plans for Kodi Leia and Kodi Matrix

 1. Current AEL version is 0.9.9 for Kodi Krypton/Leia in Python 2.

 2. Release AEL 0.10.0 for Kodi Krypton/Leia in Python 2. Do this ASAP. Minimal changes with respect to 0.9.9. This version will receive only easy-to-fix patches.

 3. Release AEL 1.0.0 for Kodi Matrix in Python 3. Possibly breaking changes in the setups.

    a. Implement the CID, PID, RAD and ATD.

    b. New Launcher/ROM artwork fields.

    c. Deprecate `<path_xxxxx>`.

    d. In the Launcher DB add the `audit_xxxxx` fields. In the ROMs DB add the additional `m_xxxxx` fields and the `i_xxxxx` fields.

    e. Rename the launcher options to `opt_xxxxx`

    f. In ROMs DB, make `genre` from a `str` into a `list`.

    g. Add the new multidisc fields and implement the multidisc engine.

    h. Make sure all Chrisism new features work as expected.

### Kodi main directories

All these directories referred to Linux

`special://home` is mapped to `/home/[user_name]/.kodi/`

`ADDON_CODE_DIR` is mapped to `/home/[user_name]/.kodi/addons/[addon_id]/`

`ADDON_DATA_DIR` is mapped to `/home/[user_name]/.kodi/userdata/addon_data/[addon_id]/`

### New AEL platform and ROM model

These changes improve the AEL experience and smooths the transition to the Kodi games database.

#### Artwork filename in PID, CID

Every piece of artwork has a default name with no number at the end. Additional artwork follow the Kodi extrafanart name convention, that is, adding a number at the end of the filename.

```
artname.png
artname1.png
artname2.png
artname_comment.png  --> Not implemented yet.
artname1_comment.png --> Not implemented yet.
```

#### Platform information directory (PID)

Relevant settings:

 * AEL addon settings, `platform_info_path`.

 * AEL addon settings, `pid_naming_scheme` with values {P_LONG_NAME, P_SHORT_NAME, P_COMPACT_NAME}.

If `platform_info_path` is not set (default) then an internal directory `ADDON_DATA_DIR/pid` is used.

The PID can be used to automatically import ROM Launcher metadata and assets at launcher creation time by importing an XML file or using the launcher creation wizard. The metadata/artwork for the launcher is searched based on the launcher platform.

The PID can be used to scan for images in the **Edit Launcher** menu, **Change launcher artwork**.

The layout of the PID is the following.

```
<pid>/<pname>/<pname>.nfo
<pid>/<pname>/banner.png
<pid>/<pname>/clearlogo.png
<pid>/<pname>/controller.png --> Picture of controller.
<pid>/<pname>/fanart.png
<pid>/<pname>/media.png      --> Picture of cartridge, CD, etc.
<pid>/<pname>/icon.png
<pid>/<pname>/poster.png
<pid>/<pname>/system.png     --> Picture of the system, SS picture or illustration.
```

`<pname>` is the standardized platform name. Extra artwork is supported for every asset, for example. `banner.png`, `banner1.png`, `banner2.png`. When scanning for artwork the order of the platform name to generate the file names is: long name, short name, compact name. When saving artwork the setting `pid_naming_scheme` sets the platform name to use.

#### ROM asset directory (RAD)

Relevant settings:

 * AEL addon settings, `rom_asset_path`.

 * AEL addon settings, `rad_naming_scheme` with values {P_LONG_NAME, P_SHORT_NAME, P_COMPACT_NAME}.

If the RAD is used, all ROMs belonging to the same platform share the same artwork. All subdirectories inside the RAD are created automatically if they don't exist, at ROM scanning time and at ROM artwork scraping time.

If `rom_asset_path` is not set user must specify a `<ROM_asset_path>` in the Launcher.

```
<rad>/<pname>/3dboxes/<ROM_name>.png
...
<rad>/<pname>/titles/<ROM_name>.png
<rad>/<pname>/trailers/<ROM_name>.png
```

Arcade/MAME and No-Intro games use different sets of artwork as specified in the following table. Table sorting order: No-Intro exclusives, MAME/Arcade exclusives, all games common. `(new)` means a new database field in AEL. `(auto)` means that can be autogenerated from other pieces of artwork with an XML template.

In `launchers.xml` and in the ROMs database include all fields for simplicity. Then, depending on the launcher platform use some fields or others.

| Important | Artname       | No-Intro available | MAME available |
|-----------|---------------|--------------------|----------------|
|           | `boxbacks`    | yes                |                |
| ***       | `boxfronts`   | yes                |                |
|           | `boxspines`   | yes (new)          |                |
|           | `boxtextures` | yes (new) (auto)   |                |
|           | `cartridges`  | yes                |                |
|           | `cabinets`    |                    | yes            |
|           | `cpanels`     |                    | yes            |
|           | `PCBs`        |                    | yes            |
|           | `3dboxes`     | yes (auto)         | yes (auto)     |
|           | `banners`     | yes                | yes            |
|           | `bezels`      | yes (new)          | yes (new)      |
|           | `clearlogos`  | yes                | yes            |
|           | `fanarts`     | yes (auto)         | yes (auto)     |
|           | `flyers`      | yes                | yes            |
|           | `manuals`     | yes                | yes            |
|           | `maps`        | yes                | yes            |
| ***       | `snaps`       | yes                | yes            |
| ***       | `titles`      | yes                | yes            |
|           | `trailers`    | yes                | yes            |

#### Category information directory (CID)

Relevant settings:

 * AEL addon settings, `category_info_path`.

`category_info_path` is a read-only path. Metadata/asset scraping of Categories is not supported in AEL.

Same as the PID but used for Category metadata NFO files and artwork files. User must place metadata NFO files and artwork files on disk.

```
<cid>/<cname>/<cname>.nfo
<cid>/<cname>/banner.png
<cid>/<cname>/clearlogo.png
<cid>/<cname>/fanart.png
<cid>/<cname>/icon.png
<cid>/<cname>/poster.png
```

#### AEL theme directory (ATD)

Relevant settings:

 * AEL addon settings, `ael_theme_path`.

The default ATD is distributed with AEL in `ADDON_CODE_PATH/media/theme`.

If the user wants to change the AEL theme then it must change the ATD path in AEL settings and then execute an utility to refresh the theme images.

I think the best idea is to store the AEL theme information in `launchers.xml` and to create a default time the first time the addon is run.

```
<atd>/Browse_AEL_Offline_<arttype>.png
<atd>/Browse_by_Category_<arttype>.png
...
<atd>/Utilities_<arttype>.png
```

#### No-Intro DAT directory

Write me. Have a look at the current AEL implementation.

#### Redump DAT directory

Write me.

#### Canonical example of Launcher XML file

Current versions of AEL use the `<ROM_asset_path>` and the `<path_xxxxx>` tags.

Future AEL versions use either the RAD or use the per-launcher `<ROM_asset_path>` with the `<subpath_xxxxx>` tags in case the user wants to change the default artwork subdirectory names. If the user uses the RAD then the tags `<subpath_xxxxx>` are ignored.

If the user wants to use the RAD then `<ROM_asset_path>RAD</ROM_asset_path>`. Also, using the RAD is the default if the tag is missing or empty.

If the user wants the artwork next to ROMs then `<ROM_asset_path>NextToROMs</ROM_asset_path>`. **NOTE** Do not implement this option in AEL but could be needed in the Kodi Games Database.

```
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<advanced_emulator_launcher_configuration>
<!-- New category. This allows to set the metadata/artwork directories -->
<main>
  <!-- This allows to set the metadata/artwork directories and the change is permanent. -->
  <CID_path></CID_path>
  <PID_path></PID_path>
  <RAD_path></RAD_path>
  <ATD_path></ATD_path>
</main>

<launcher>
  <name>PlayStation (Retroarch)</name>
  <platform>Sony PlayStation</platform>
  <category>SONY</category>
  <application>/home/kodi/bin/retroarch</application>
  <args>-L /home/kodi/bin/libretro/mednafen_psx_libretro.so -f -v &quot;$rom$&quot;</args>
  <Options>Blocking</Options>
  <ROM_path>/home/kodi/AEL-ROMs/sony-psx/</ROM_path>
  <ROM_ext>chd</ROM_ext>
  <ROM_asset_path>/home/kodi/AEL-assets/sony-psx/</ROM_asset_path>
  <path_title> --> Deprecated
  <path_snap>  --> Deprecated
  ...
  <subpath_title>
  <subpath_snap>
  ...

  <Launcher_NFO>Playstation.nfo</Launcher_NFO>
  <year>1994</year>
  <genre>Fifth generation console</genre>
  <developer>SONY</developer>
  <rating></rating>
  <plot>The PlayStation is a home video game console released on 3 December 1994.</plot>

  <Asset_Prefix>PlayStation</Asset_Prefix>
  <s_icon />
  <s_fanart />
  <s_banner />
  <s_poster />
  <s_clearlogo />
  <s_controller />
  <s_trailer />
</launcher>
</advanced_emulator_launcher_configuration>
```

#### Examples of Launcher creation

**Launcher metadata and artwork taken from PID. ROMs artwork in RAD**

Category metadata/artwork taken from CID if the category is new.

```
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<advanced_emulator_launcher_configuration>
<launcher>
  <name>PlayStation (Retroarch)</name>
  <category>SONY</category>
  <platform>Sony PlayStation</platform>
  <application>/home/kodi/bin/retroarch</application>
  <args>-L /home/kodi/bin/libretro/mednafen_psx_libretro.so -f -v &quot;$rom$&quot;</args>
  <ROM_path>/home/kodi/AEL-ROMs/sony-psx/</ROM_path>
  <ROM_ext>chd</ROM_ext>
  <!-- This tag be omitted or empty because this is the default -->
  <ROM_asset_path>RAD</ROM_asset_path>
</launcher>
</advanced_emulator_launcher_configuration>
```

**Launcher metadata and artwork taken from PID. ROMs artwork in custom dir**

```
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<advanced_emulator_launcher_configuration>
<launcher>
  <name>PlayStation (Retroarch)</name>
  <category>SONY</category>
  <platform>Sony PlayStation</platform>
  <application>/home/kodi/bin/retroarch</application>
  <args>-L /home/kodi/bin/libretro/mednafen_psx_libretro.so -f -v &quot;$rom$&quot;</args>
  <ROM_path>/home/kodi/AEL-ROMs/sony-psx/</ROM_path>
  <ROM_ext>chd</ROM_ext>
  <ROM_asset_path>/home/kodi/AEL-assets/sony-psx/</ROM_asset_path>
  <!-- Only if user want to change the default artwork subdirectory names -->
  <subpath_title />
</launcher>
</advanced_emulator_launcher_configuration>
```

### Implementation algorithms

Keep in mind standalone launchers and special launchers in future AEL releases.

#### Importing a Launcher XML file

**Algorithm for metadata**

 1. Read the metadata tags `<year>`, `<genre>`, ...

 2. Read the Launcher NFO file if set with `<Launcher_NFO>`.

 3. **ONLY FOR ROM Launchers** Search for the Launcher NFO file in the PID.

 4. The priority to set the metadata is; 1) metadata tags, 2) Launcher NFO file and 3) PID. Database `m_xxxxx` fields are set.

**Algorithm for artwork**

 1. Read the absolute-path artwork tags `<s_xxxxx>`.

 2. Read the `<Asset_Prefix>` tag and scan for artwork.

 3. **ONLY FOR ROM Launchers** Search for launcher artwork in the PID depending on the platform name.

 4. The priority to set the artwork is; 1) absolute-path tags, 2) `<Asset_Prefix>` and 3) PID. If more than one piece of artwork is found then an image selection dialog is shown to the user. Database `s_xxxxx` fields are set.

#### Full configuration XML saving/backup

When saving a XML backup of all Categories and Launchers the full metadata tags `<year>`, `<genre>`, ... and the absolute-path artwork tags `<s_xxxxx>` are always used. The following tags are never used; `<Launcher_NFO>`, `<Asset_Prefix>`. The `<subpath_xxxxx>` tags are only saved if the RAD is not used and the `<subpath_xxxxx>` value is different from the default for the platform.

#### Saving a Launcher XML file

Same as the full configuration backup.

#### ROM scanner scanning for artwork

**Algorithm for metadata**

 1. Write me. In principle the current AEL implementation should be OK.

**Algorithm for artwork**

 1. If `<ROM_asset_path>` has a value of `RAD` then use the RAD. Create the platform directory and the artwork subdirectories in the RAD.

 2. If `<ROM_asset_path>` is a custom directory then use it. Create the artwork subdirectories.

#### Importing/Saving a Category XML file

Same as a Launcher import/saving.

### Current menus in 0.9.8

Context menu **Edit Launcher**, submenu **Manage ROMs ...**:
```
'Choose ROMs default artwork ...',
'Manage ROMs asset directories ...',
'Rescan ROMs local artwork',
'Scrape ROMs artwork',
'Remove dead/missing ROMs',
'Import ROMs metadata from NFO files',
'Export ROMs metadata to NFO files',
'Delete ROMs NFO files',
'Clear ROMs from launcher',
```

Context menu **Edit Launcher**, submenu **Audit ROMs / Launcher view mode ...**:
```
'Change launcher display mode (now {}) ...'.format(display_mode_str),
'Add No-Intro/Redump XML DAT ...' OR 'Delete No-Intro/Redump DAT: {}'
'Create Parent/Clone DAT based on ROM filenames',
'Display ROMs (now {}) ...'.format(launcher['nointro_display_mode']),
'Update ROM audit',
```

**Display modes** are `LAUNCHER_DMODE_FLAT`, `LAUNCHER_DMODE_PCLONE` and `LAUNCHER_DMODE_1G1R`.
PCLONE and 1G1R are the same, the difference is that in 1G1R the ROM Context 
Menu **Show clones** is displayed and Parents are launcher automatically. AML now has
FLAT and 1G1R modes only.

**Display filters** are `NOINTRO_DMODE_ALL`, `NOINTRO_DMODE_HAVE`, `NOINTRO_DMODE_HAVE_UNK`,
`NOINTRO_DMODE_HAVE_MISS`, `NOINTRO_DMODE_MISS`, `NOINTRO_DMODE_MISS_UNK`, `NOINTRO_DMODE_UNK`.

Current fields in Launchers database:

```
'nointro_xml_file' : '',
'nointro_display_mode' : NOINTRO_DMODE_ALL,
'launcher_display_mode' : LAUNCHER_DMODE_FLAT,
```

Current fields in ROMs database:

```
'disks' : [],
'nointro_status' : 'Miss',
'pclone_status' : 'Parent',
'cloneof' : '',
```

### Menus in future AEL releases

Context menu **Edit Launcher**, submenu **Manage ROMs ...**:

```
'Choose ROMs default artwork...',
'Manage ROMs asset subdirectories...',
'Rescan ROMs local artwork',
'Scrape ROMs artwork',
'Export Launcher gamelist.xml'
'Import ROMs metadata from NFO files',
'Export ROMs metadata to NFO files',
'Delete ROMs NFO files',
'Delete ROMs from launcher',
```

Context menu **Edit Launcher**, submenu **Audit ROMs / Launcher view mode ...**:

```
'Launcher display mode (now {})...'.format(display_mode_str),
'Audit display filter (now {})...'.format(launcher['display_filter']),
'Audit launcher ROMs',
'Undo ROM audit (remove missing ROMs)',
'Add custom XML DAT ...' OR 'Delete custom XML DAT',
```

**Launcher display modes** are `LAUNCHER_DMODE_FLAT` (default) and `LAUNCHER_DMODE_PCLONE`.

**Launcher audit status** are `AUDIT_STATE_ON`, `AUDIT_STATE_OFF` (default).

**Launcher audit display filter** `AUDIT_FILTER_ALL` (default), `AUDIT_FILTER_HAVE`, `AUDIT_FILTER_HAVE_UNK`, `AUDIT_FILTER_HAVE_MISS`, `AUDIT_FILTER_MISS`, `AUDIT_FILTER_MISS_UNK`, `AUDIT_FILTER_UNK`. For now, always display Extra ROMs.

### Future AEL guidelines

The **Parent/Clone information** is ALWAYS computed, regardles of the audit status, whenever the launcher ROMs change.

The **ROM region information** is ALWAYS computed, regardless of the audit status, whenever the launcher ROMs change.

The **Launcher display mode** is always available.

The **Launcher audit display filter** is available only if the audit status `audit_state` is `AUDIT_STATE_ON`.

The Parent of the Parent/Clone group is chosen according to the preferred Region and Language settings. User selects the preferred Region and Language with global settings. These global settings may be overriden with Launcher-specific settings (launcher specific settings not implemented at the moment).

The ROM Audit is very easy to do. The difficult part is to make the Parent/Clone groups and choosing the parent ROM, or in other words, sort the ROMs in the parent/clone group.

Relevant settings:

 * **Primary ROM region** in AEL addon settings.

 * **Secondary ROM region** in AEL addon settings.

 * **Primary ROM language** in AEL addon settings.

 * **Secondary ROM language** in AEL addon settings.

Future fields in Launchers database:

```
'audit_state' : AUDIT_STATE_ON or AUDIT_STATE_OFF,  Reports if audit is ON or not
'audit_auto_dat_file' : '',                         Filled in automatically
'audit_custom_dat_file' : '',                       Previous nointro_xml_file
'audit_display_mode' : from AUDIT_DMODE_LIST,       Previous nointro_display_mode
'launcher_display_mode' : LAUNCHER_DMODE_FLAT or LAUNCHER_DMODE_PCLONE
```

Future ROMs database fields:

```
'm_cloneof' : '',              Override the ROM parent. ROM_base_noext (read-only field)
'm_regions' : ['', ''],        Override the ROM regions (read-only field)
'm_languages' : ['', ''],      Override the ROM languages (read-only field)
'i_audit_status' : str,        Determined by the ROM Audit exclusively, former nointro_status
'i_pclone_status' : str,       Based on i_cloneof, used to set skin properties, former pclone_status
'i_cloneof' : ROMID_MD5_str,   ROM ID of the final parent ROM, former cloneof
'i_extra_ROM' : bool,          If True ROM is an extra ROM, false otherwise
'i_order' : int,               Position of this ROM in the Parent/Clone group. 0 is the parent ROM
'i_regions' : ['', ''],        Same as m_region
'i_languages' : ['', ''],      Same as m_language
'i_tags' : ['', ''],           Always extracted from filename
                               Other unrecognised tags not region or language
```

Metadata `m_xxxxx` fields indicate user-configurable fields used to override automatic `i_xxxxx` fields. `i_xxxxx` indicate AEL internal and automatic fields, users are not able to edit directly.

`i_audit_status` can have values from list `AUDIT_STATUS_LIST`.

`i_pclone_status` can have values from list `PCLONE_STATUS_LIST`.

Rename launcher fields `finished`, `toggle_window`, `non_blocking`, `multidisc`, to `opt_finished`, `opt_toggle_window`, `opt_non_blocking`, `opt_multidisc`.

### Computation of the Parent/Clone ROM groups and group order

To keep things simple only use the ROM filename and the AEL Offline Scraper database for Parent/Clone computation. Do not use No-Intro and Redump DATs.

A report of the PClone group generation should be generated so the user can check for errors or unwanted configurations.

 1. First Parent/Clone groups are computed:
 
    1. The Offline Scraper database will be used first.
       For found ROMs `i_cloneof`, `i_regions` and `i_languages` will be taken from the database.

    3. For Unknown ROMs, the ROM basename will be used to compute `i_cloneof` and `i_regions`
       and `i_languages` extracted from the filename.

    4. The fiels `m_cloneof`, `m_region` and `m_language` in the ROM metadata override any of 
       the `i_*` fields.

 2. With the fields `i_cloneof`, `i_regions`, `i_languages` and `i_tags` the order in the Parent/Clone group is calculated:

    1. User chooses the primary and secondary ROM regions in AEL settings from a fixed list.

    2. User chooses the primary and secondary ROM languages in AEL settings from a fixed list.

    3. Other tags like `(Rev X)` are used to choose the preferred Parent in the set.

       AEL needs to have an histogram of all the No-Intro and Redump tags and use the information when building the Parent/Clone groups according to the settings.

    4. PClone groups are reordered according to the user settings. The Parent of the group will
       be the first ROM in the set.

    5. `i_cloneof` is updated to reflect the new Parent of each set.

    6. `i_order` is updated to reflect the ROM positions in the set.

    6. The file `roms_<Launcher_name>_PClone_index.json` is created.
       This file is used when rendering the PClone group list when the user select the
       context menu "Show clone ROMs".

    7. To render the Parent ROMs in PCLONE launcher display mode open the ROM JSON database
       and render only the Parent ROMs.

**Potential problems**

 * What if the parent of a PClone group is a Missing ROM?

   1. If all ROMs in the PClone group are Missing choose the Parent ROM as usual.

   2. Otherwise, short the ROMs in the group according to the user preferences and choose
      the first Have or Unknown ROM as Parent.

 * What if the user wants to force a specific Parent? How to do this?

   1. The Parent can be changed with the ROM Region and ROM Language settings.

   2. Maybe having a read-only setting bool `m_forceparent`??? This can create a conflict in the settings that must be solved.

 * What if there is a conflict when creating the Parent/Clone groups? For example, the No-Intro DAT says the Parent of a ROM is A and the user sets the parent of the ROM to B.

   1. A report of the Parent/Clone groups must be created so the user knows what happened and fix any error or misconfiguration. This report can be read using the Launcher context menu.

### Computation of the ROM Audit

 1. Only ROMs in the main ROM directory are audited.

 2. All ROMs in the extra ROM directory are Extra ROMs. Extra ROMs can be ROM hacks, etc., which are not in the official DATs but may be included in the Offline Scraper database.

 3. The XML DAT for No-Intro ROMs is chosen automatically from the No-Intro DAT directory as a function of the platform launcher.

 4. The XML DAT for Redump ROMs is chosen automatically from the Redump DAT directory as a function of the platform launcher.

 5. Users can manually configure a custom XML DAT file for every launcher. In this case, the automatic DAT selection is ignored.

 6. The Offline Scraper database can be used for the ROM Audit instead of an external DAT XML file.

### Examples of ROM Audit and Parent/Clone generation

Complete example of SNES ROMs including all cases except multidisc ROMs.

```
Kaizo Mario World (Japan)                       -- EXTRA ROM / Different basename from any ROM in set
Super Mario World - Super Mario Bros. 4 (Japan) -- CLONE ROM / Different basename from any ROM in set
Super Mario World (Europe)                      -- CLONE ROM
Super Mario World (Europe) (Rev 1)              -- PARENT ROM / According to No-Intro DAT
Super Mario World (Japan) (En) (Arcade) [b]     -- MISSING ROM / CLONE ROM
Super Mario World (USA)                         -- CLONE ROM
```

To be written...

### Multidisc support

In the current implementation there is a virtual ROM in the database that represents all the ROMs in the set. The virtual multidisc ROM have the ROM basenames of the set in the `disks` list. This implementation has problems with the ROM audit because not all the real ROMs are in the database.

#### Multidisc ROM scanner implementation (current)

 1. Determine if the ROM is a multidisc ROM using the ROM filename. If so, determine the **set name** (ROM basename excluding the multidisc tag), the **disk name** (ROM basename), the **set index**, and so on. For example, set name = `Final Fantasy VII (USA)`, disk name = `Final Fantasy VII (USA) (Disc 3)` and set index = `3`.

 2. Check if the set exists in the database. Linear search of the set name in the base name of the `filename` field of all ROMs.

 3. If the set is not found:

    a. Set the `filename` field to ROM_dir + set name, for example `/home/kodi/ROMs/Final Fantasy VII (USA)`. It is important to have this name because the `filename` field could be used to determine the ROM artwork if option `<ROM_asset_path>NextToROMs</ROM_asset_path>` is set.

    b. The ROM basename is added to the `disks` list.

    c. Asset names will have the basename of the set `Final Fantasy VII (USA)`.

 4. If the set is found (set ROM already exists):

    a. The disk name is added to the `disks` list.

    b. `disks` list is reordered so ROMs have consecutive order.

```
m_title : whatever_str,
filename = '/home/kodi/ROMs/Final Fantasy VII (USA)'
disks = ['Final Fantasy VII (USA) (Disc 1).cue', 'Final Fantasy VII (USA) (Disc 3).cue']
```

ROMs not in a set have an empty `disks` list.

This implementation is safe if there are No-Intro missing ROMs in the set.

At launching time, users selects from a select dialog of the basenames of the roms of the set which one to launch.

#### Multidisc ROM scanner implementation (new)

In the new implementation for each multidisc group there is a **multidisc virtual set ROM** that represents the whole set and also there is a **multidisc ROM** database entry for each ROM in the set. This resolves the problem with the ROM audit of multidisc ROMs.

The `filename` field of the **multidisc virtual set ROM** is set to `ROM.getDir()` + `set_name`, for example `/home/ROMs/psx/Final Fantasy VII (USA)`. It is important to have this name because the `filename` field could be used to determine the ROM artwork if option `<ROM_asset_path>NextToROMs</ROM_asset_path>` is set.

The `disk_status` field can be determined on the fly from `disks` and `disk_parent`, for example to differentiate a normal ROM from a multidisc ROM. However, the field `disk_status` is included to speed up ROM rendering and processing.

Launcher multidisc fields in `launchers.xml`:

```
'multidisc' : bool,
```

Example of a normal ROM in the ROM database:

```
disk_status : MULTIDISC_NONE,
disks : [],
disk_parent : '',
```

Example of a multidisc virtual set ROM (multidisc ROM that represents the set):

```
m_title : 'Final Fantasy VII (USA)',
filename : '/home/ROMs/psx/Final Fantasy VII (USA)',
disk_status : MULTIDISC_VIRTUAL,
disks : [ROMID_1_MD5_str, ROMID_2_MD5_str, ...],
disk_parent : '',
```

Example of a multidisc ROM (multidisc ROM that belongs to a set):

```
m_title : 'Final Fantasy VII (USA) (Disc 1)',
filename : '/home/ROMs/psx/Final Fantasy VII (USA) (Disc 1).cue',
disk_status : MULTIDISC_ROM,
disks : [],
disk_parent : ROMID_MD5_str,
```

**ROM scanner algorithm for multidisc sets**

If `multidisc` is `True` and the user sets it to `False` then the **multidisc virtual set ROMs** are removed and the **multidisc ROMs** converted to normal ROMs. If `multidisc` is `False` and then the user sets it to `True` the ROM scanner must be run to create the **multidisc virtual set ROMs** and to convert the multidisc normal ROMs into **multidisc ROMs**.

Maybe doing the ROM scanning for the multidisc case in one pass is difficult. It could be simpler to do a first pass to scan and process metadata/assets of all ROMs, and then do a second pass to remove dead **multidisc virtual set ROM** and to create new **multidisc virtual set ROM**.

Another feature to code is a consistency checker that verifies the consistency of the whole ROMs database in AEL. This could be necessary every time the ROMs in the launcher are changed (added or removed).

**IMPORTANT** For passes that modify the ROM list/dictionary be careful with modifying lists/dictionaries when iterating.

 1. First pass is to remove dead ROMs (`filename` not found), No-Intro/Redump missing ROMs and **multidisc ROMs**. Do not remove **multidisc virtual set ROMs**.

 2. In the second pass remove dead **multidisc virtual set ROMs**. Dead **multidisc virtual set ROMs** have zero **multidisc ROMs** in the set. Traverse all ROMs, for each **multidisc virtual set ROM** check that the child **multidisc ROMs** exist. If a **multidisc ROMs** cannot be found by ROM ID then remove it from the `disks` list. If at the end the `disks` field is empty then remove this **multidisc virtual set ROM**.

    After this point all **multidisc virtual set ROMs** are valid.

 3. In the third pass process each real ROM as usual. Traverse found filenames in the ROM path and scrape metadata and assets for new ROMs.

 4. In the fourth pass add No-Intro/Redump missing ROMs if audit is enabled. Missing ROMs are never scraped for metadata/assets. Note that missing ROMs can be **multidisc ROMs**.

 5. In the fifth pass create the new **multidisc virtual set ROMs** and check for coherence of existing **multidisc virtual set ROMs**. Traverse all ROMs and for each ROM determine if the ROM is a **multidisc ROM**. If the ROM is a **multidisc ROM** then determine the **set name** (ROM basename excluding the multidisc tag), the **disk name** (ROM basename), the **set index**, and so on. For example, set name = `Final Fantasy VII (USA)`, disk name = `Final Fantasy VII (USA) (Disc 3)` and set index = `3`. 

    a. If the ROM is a **multidisc ROM** and the **multidisc virtual set ROM** is not found then is a new **multidisc virtual set ROM**. Create the **multidisc virtual set ROM** and process metadata and assets for this new **multidisc virtual set ROM**.

    b. Else if the ROM is a **multidisc ROM** and the **multidisc virtual set ROM** is found then verify that the multidisc ROM is on the `disks` list. If not issue a warning.

    c. Else if the ROM is a **multidisc virtual set ROM** then verify that all set multidisc ROMs can be found. For each not found multidisc ROM issue a warning.

### No-Intro ROM names

The official No-Intro naming convention PDF can be downloaded from [DAT-o-matic](https://datomatic.no-intro.org/) website.

The only mandatory elements are the **ROM title** and the **ROM region**. All other tags are optional.

### Redump/Trurip/TOSEC ISO names

[No-Intro](http://www.no-intro.org/index.html)

[TOSEC naming convention](http://www.tosecdev.org/tosec-naming-convention)

| Organisation | Name example                                                  |
|--------------|---------------------------------------------------------------|
| **TOSEC**    | `Final Fantasy VII (1999)(Square)(NTSC)(US)(Disc 1 of 2).cue` |
|              | `Final Fantasy VII (1999)(Square)(NTSC)(US)(Disc 2 of 2).cue` |
| **Trurip**   | `Final Fantasy VII (EU) - (Disc 1 of 2).cue`                  |
|              | `Final Fantasy VII (EU) - (Disc 2 of 2).cue`                  |
| **Redump**   | `Final Fantasy VII (USA) (Disc 1).cue`                        |
|              | `Final Fantasy VII (USA) (Disc 2).cue`                        |

### TOSEC/Trurip/Redump image formats

| TOSEC       | Redump  | Trurip          |
|-------------|---------|-----------------|
| cue,iso,wav | cue,bin | cue,img,ccd,sub |

### ROM Collections

Way of storing ROM Collections when saving the collection. This layout makes easier to place all the collections in one directory.

```
Sonic the Hedgehog.json
Sonic the Hedgehog_banner.png
Sonic the Hedgehog_fanart.png
Sonic the Hedgehog_icon.png
Sonic the Hedgehog_poster.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_fanart.png         --> megadrive
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_title.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_snap.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe, Brazil)_fanart.png --> sms
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe, Brazil)_title.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe, Brazil)_snap.png
```

There could be more than one image that will be shown to the user when importing the ROM Collection JSON file. The user then chooses what image to import. This applies to the artwork of the collection itself and to the Collection ROMs:

```
Sonic the Hedgehog.json
Sonic the Hedgehog_fanart.png
Sonic the Hedgehog_fanart1.png
Sonic the Hedgehog_fanart2.png
Sonic the Hedgehog_fanart3.png
```

If two ROMs in different platforms have the same filename then a platform compact name suffix is added to resolve the filename collision. Platform Long, Short and Compact names can be used:

```
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_megadrive_fanart.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_megadrive_title.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_megadrive_snap.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_sms_fanart.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_sms_title.png
Sonic the Hedgehog/Sonic The Hedgehog (USA, Europe)_sms_snap.png
```

### listitem.setInfo() overlay values and effects

`listitem.setInfo('video', {'overlay'  : 4})`

Kodi Krypton Estuary displays a small icon to the left of the listitem title that can be changed with the overlay property value. Overlay values are defined in [GUIListItem]:

```
enum GUIIconOverlay {
    ICON_OVERLAY_NONE = 0,
    ICON_OVERLAY_RAR,
    ICON_OVERLAY_ZIP,
    ICON_OVERLAY_LOCKED,
    ICON_OVERLAY_UNWATCHED,
    ICON_OVERLAY_WATCHED,
    ICON_OVERLAY_HD
};
```

[setInfo]: http://mirrors.xbmc.org/docs/python-docs/16.x-jarvis/xbmcgui.html#ListItem-setInfo
[GUIListItem]: https://github.com/cisco-open-source/kodi/blob/master/xbmc/guilib/GUIListItem.h

### Misc stuff

Nothing at the moment.
