summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-05-29 11:09:46 +0000
committerCoprDistGit <infra@openeuler.org>2023-05-29 11:09:46 +0000
commit43c783cd4049db938cd8dae541959f11b2767ff1 (patch)
tree78f3c8ebb63cdd514bbde9bfdc304a4d3ee40c3f
parentff4c65e5e2d39a7930c4415534f886e55037e8cc (diff)
automatic import of python-naomiutils
-rw-r--r--.gitignore1
-rw-r--r--python-naomiutils.spec3095
-rw-r--r--sources1
3 files changed, 3097 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..4182598 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/naomiutils-0.5.4.tar.gz
diff --git a/python-naomiutils.spec b/python-naomiutils.spec
new file mode 100644
index 0000000..f9f64d2
--- /dev/null
+++ b/python-naomiutils.spec
@@ -0,0 +1,3095 @@
+%global _empty_manifest_terminate_build 0
+Name: python-naomiutils
+Version: 0.5.4
+Release: 1
+Summary: Code libraries for working with Naomi ROMs and EEPROMs.
+License: Public Domain
+URL: https://github.com/DragonMinded/netboot
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/1d/62/55561f2251ae03ce004bcbca3d9e9e5f7cc56273badb4a5f46bd2fa2be2e/naomiutils-0.5.4.tar.gz
+BuildArch: noarch
+
+Requires: python3-arcadeutils
+Requires: python3-dragoncurses
+
+%description
+# naomi
+
+Collection of routines written in Python for manipulating Naomi ROM and EEPROM
+files. This is geared towards enthusiasts building their own netboot servers or
+RPI setups and provides libraries for examining ROM and manipulating ROM headers
+as well as attaching EEPROM settings to ROM files and manipulating their contents.
+It is fully typed and requires a minimum of Python 3.6 to operate.
+
+## NaomiEEPRom
+
+The NaomiEEPRom class provides high-level accessors to a 128-byte Naomi EEPROM
+dump as obtained through a ROM dumper or from an emulator's saved state. It handles
+correcting various CRCs as well as allowing high-level access to the duplicated
+game and system settings sections. Use this to create or manipulate a raw EEPROM
+data file.
+
+### Default Constructor
+
+Takes a single byte argument "data" and verifies that it is a valid 128-byte EEPROM
+before returning an instance of the `NaomiEEPRom` class used to manipulate that
+data. If any of the CRCs do not match this will raise a `NaomiEEPRomException`.
+
+### NaomiEEPRom.default
+
+An alternate constructor that takes a single byte argument "serial" and an optional
+byte argument "game_defaults" and creates a valid EEPROM based on this data, returning
+an instance of the `NaomiEEPRom` class that can be used to manipulate this newly
+created EEPROM. The serial argument should be exactly bytes and begin with a "B",
+followed by two characters and finally a digit, as represented by a bytestring. This
+is a Naomi system restriction. Optionally, a string of bytes can be given in the
+"game_defaults" section which will be used to determine the length and default
+values of the game section of the EEPROM.
+
+### NaomiEEPRom.validate
+
+A static method that takes a byte argument "data" and checks it for validity. This
+includes making sure the length is 128 bytes and that all CRCs are correct. Optionally
+you can pass in the boolean keyword argument "only_system" set to True to only check
+that the system section is valid. This is useful for validating EEPROMs where the BIOS
+has written system settings but the game has not yet booted and created its own
+defaults yet. You can use this function to ensure that passing data to the default
+constructor will not result in an exception.
+
+### data property
+
+An instance of NaomiEEPRom has the "data" property, which returns a bytes object
+representing the current 128-byte EEPROM. This will have all CRC sections fixed.
+Use the "data" property to retrieve the EEPROM for writing to a file or sending to
+a Naomi system after manipulating data using the NaomiEEPRom class. Note that this
+is read-only, you should not attempt to manipulate the raw data using this property.
+
+## serial property
+
+Returns the 4 byte serial that is found in the system section of the EEPROM. This
+will match a serial given in the `NaomiEEPRom.default` constructor when it is used.
+Use this to help determine what game an EEPROM goes with. Note that this is read-only.
+To modify the serial, create a new EEPROM with that serial. Game settings and system
+settings are not compatible across games on the Naomi platform.
+
+## length property
+
+The length in bytes as an integer of the game section of the EEPROM. If the game section
+is not valid this return 0 bytes. Otherwise it returns the length of the game section
+itself. This property is writeable. If you provide it a new value, the game section
+will be resized to that length. Use this to determine the bounds of the `game` section
+as documented below, as well as to resize the `game` section.
+
+## system property
+
+Returns a bytes-like wrapper object representing the system section of the EEPROM.
+This operates like a bytearray object in Python. That means you can access or mutate
+any byte or section in the system area using this property. Note that this wrapper
+object takes care of reading from and writing to both mirrors of the system section in
+the EEPROM file as well as ensuring that the CRC is correct. Note also that the system
+section is hard-coded to 16 bytes in length which cannot be modified. This is a system
+restriction on the Naomi platform. Much like bytes objects in python, accessing a single
+byte returns an integer in the range of 0-255, but accessing a range returns a bytes
+object.
+
+A simple example of reading bytes 6-8 of the system section:
+
+```
+eeprom = NaomiEEPRom(somedata)
+print(eeprom.system[6:8]) # Will print a bytes object of length 2.
+```
+
+A simple example of writing bytes 10-12 of the system section:
+
+```
+eeprom = NaomiEEPRom(somedata)
+eeprom.system[10:12] = b"\x12\x34"
+```
+
+## game property
+
+Returns a bytes-like wrapper object representing the game section of the EEPROM. This
+operates identically to the `system` property as documented above, only it accesses the
+game section of the EEPROM. Note that for this to work properly, the game section needs
+to be initialized by setting the `length` property on the instance of `NaomiEEPRom`. If
+you are manipulating an existing EEPROM file, this property will already be set for you.
+
+Note that this wrapper object includes a `valid` property which returns if the current
+section is valid in the EEPROM you are manipulating. This will always be `True` for
+the system section. However, if you access the game section on a newly-created EEPROM
+without setting defaults or a length, the game property's `valid` property will return
+`False`.
+
+An example of verifying that the game section is valid:
+
+```
+eeprom = NaomiEEPRom.default(serial=b"BBG0")
+print(eeprom.game.valid) # Will print "False" as the EEPROM was created without a game section default.
+eeprom.length = 20
+print(eeprom.game.valid) # Will print "True" as the EEPROM game section was initialized to be 20 bytes long.
+```
+
+## NaomiRom
+
+The NaomiRom class provides high-level accessors to a Naomi ROM header as found
+at the beginning of a ROM file suitable for netbooting. It handles decoding all
+sections of the ROM header as well as allowing modification and even creation of
+new ROM header sections given valid data. Use this if you wish to manipulate or
+create your own Naomi ROM files form scratch.
+
+### Default Constructor
+
+Takes a single byte argument "data" and uses it as the ROM image where the header
+will be extracted. Note that there is no CRC over the ROM header so any data that
+is 1280 bytes or longer will appear valid.
+
+### NaomiRom.default
+
+An alternate constructor that creates an entirely blank Naomi ROM containing no
+loaded executable or test sections and no ROM name. Use this when you want to
+programatically construct a ROM image, such as when you are building a final ROM
+in a homebrew program you are building for the Naomi platform.
+
+### valid property
+
+An instance of NaomiRom has the "valid" property which will be "True" when the ROM
+passed into the constructor is a valid Naomi ROM and "False" otherwise. This is a
+read-only property as the vailidity of a ROM is entirely dictated by the data
+passed into the constructor.
+
+### data property
+
+The ROM data, as passed into the constructor for the instance of NaomiRom, or as
+created when using `NaomiRom.default` alternate constructor. Note that when any
+of the following properties are written, the `data` property will be changed to
+reflect those settings. Use this to retrieve the updated ROM after you've made
+adjustments to the values you wish to change.
+
+### publisher property
+
+The publisher of this ROM, as a string. When read, grabs the current publisher
+of the ROM image. When written, updates the publisher to the new string provided.
+
+### names property
+
+A dictionary of names indexed by region. Given the current system region, the names
+that show up here will also be the names that show up in the test menu for a given
+game. Note that there are the following constants that can be used to index into the
+names list: `NaomiRomRegionEnum.REGION_JAPAN`, `NaomiRomRegionEnum.REGION_USA`,
+`NaomiRomRegionEnum.REGION_EXPORT`, `NaomiRomRegionEnum.REGION_KOREA`, and finally
+`NaomiRomRegionEnum.REGION_AUSTRALIA`. Note that the last region, Australia, exists
+in many ROM files but is not accessible as there is no Australia BIOS for the Naomi
+platform. When read, grabs a dictionary of names of the ROM given the region. When
+written, updates the ROM names by region using the dictionary provided.
+
+### sequencetexts property
+
+A list of 8 sequence texts that are used by the game for coin insertion messages.
+Many ROMs only have the first sequence set. When read, grabs all 8 sequence texts
+and returns a list of them. When written, updates the sequence texts to the new
+list of strings provided.
+
+### defaults property
+
+A dictionary of NaomiEEPROMDefaults instance representing what defaults the BIOS will
+set in the system EEPROM section when initializing the EEPROM on first boot. Note
+that this is indexed by the same enumeration as the "names" property. When read, grabs
+the defaults and returns them. When written, extracts values from the provided
+NaomiEEPROMDefaults instances and updates the per-region defaults in the ROM accordingly.
+
+### date property
+
+A `datetime.date` instance representing what date the ROM was build and released.
+When read, returns the current date in the ROM header. When written, updates the
+date of the ROM with the new `datetime.date` provided.
+
+### serial property
+
+A 4-byte bytestring representing the serial number of the ROM. This is used to tie
+EEPROM data to the ROM itself and lets the Naomi know when to reset certain defaults.
+When read, returns the current serial from the ROM header. When written, updates the
+serial in the ROM header.
+
+### regions property
+
+A list of NaomiRomRegionEnum values representing valid regions this ROM will run under.
+Uses the same region constants as the `names` property. When read, returns a list of
+the valid regions this ROM executes under. When written, updates the list of regions
+the ROM is allowed to execute under. When booting, the Naomi BIOS will check the
+current region against this list and show an error if the current region is not
+included in the list.
+
+### players property
+
+A list of integers representing the valid number of player configurations that this
+ROM will boot under. Valid player numbers include 1, 2, 3 and 4. When read, returns
+a list of all valid number of player configurations that this game will boot with.
+When written, updates the list of player configurations. When booting, the Naomi
+BIOS will check the "Number of Players" setting in the system assignments and see
+if that setting appears in this list.
+
+### frequencies property
+
+A list of frequencies that the monitor is allowed to run at for this ROM. This
+includes the values 15 and 31. On read, returns the list of allowed frequencies.
+On write, updates the list of allowed frequencies. On boot, the Naomi BIOS will
+check the current horizontal refresh rate of the system as controlled by a DIP
+switch and show an error if it isn't in the list of allowed frequencies.
+
+### orientations property
+
+A list of strings representing the allowed orientations for the monitor for this
+ROM. The includes the values "horizontal" and "vertical". On read, returns the
+list of all acceptable orientations. On write, updates that list based on the
+provided list of strings. On boot, the Naomi BIOS will check the current "Monitor
+Orientation" setting in the system assignments and see if that orientation is
+on this list.
+
+### servicetype property
+
+A string value of either "individual" or "common" for the expected service button
+type for the ROM. On read, returns either "individual" or "common" to represent
+the current service type selected. On write, updates the service type to match
+the string provided.
+
+### main_executable property
+
+An instance of a NaomiExecutable including sections of the ROM that the Naomi
+BIOS will copy before executing the ROM, as well as the entrypoint in main RAM
+that the BIOS will jump to after copying sections. On read, returns the current
+list of sections to copy as well as the main entrypoint, as encapsulated as an
+instance of NaomiExecutable. On write, it updates the ROM to the new executable
+configuration by unpacking the NaomiExecutable instance given.
+
+### test_executable property
+
+This property is identical to the `main_executable` property, except for it
+represents the code and entrypoint that the Naomi BIOS will use when executing
+the "Game Test Mode" section of the test menu. It can be similarly read and written.
+
+## NaomiSettingsPatcher
+
+The NaomiSettingsPatcher class provides logic for attaching an EEPROM or SRAM configuration
+file to a Naomi ROM so that it can be written to the EEPROM/SRAM when netbooting that
+ROM. Note that this is not a supported feature of the Naomi platform, so it uses
+an executable stub that it attaches to the ROM in order to make this work. If you
+do not care what executable stub is attached and only want to patch settings into
+a ROM file, use the `get_default_trojan` function which will return a bytes
+object suitable for passing into a `NaomiSettingsPatcher` constructor.
+
+### Default Constructor
+
+Takes a bytes "rom" argument and a bytes "trojan" argument creates an instance of
+NaomiSettingsPatcher which can attach or retrieve previously-attached EEPROM or SRAM settings
+in a Naomi ROM file suitable for netbooting. An example of how to initialize this
+is as follows:
+
+```
+from naomi import NaomiSettingsPatcher, get_default_trojan
+
+patcher = NaomiSettingsPatcher(somedata, get_default_trojan())
+```
+
+### data property
+
+The same bytes as passed to the `NaomiSettingsPatcher` constructor. After calling
+`put_settings()` as documented below, this will be updated to the new ROM contents
+with the settings applied. A recommended workflow is to patch ROMs on-the-fly when
+netbooting by creating an instance of `NaomiSettingsPatcher` with the ROM data you
+were about to send, calling `put_settings()` with the settings you wish to attach,
+and then getting the data using this property and sending it down the wire to the
+Naomi system. Note that you can attach either an EEPROM file (128 bytes) or an SRAM
+file (32kb) but not both.
+
+### serial property
+
+An instance of NaomiSettingsPatcher has the `serial` property. When read, this
+will examine the serial of the Naomi ROM passed into the constructor and return the
+4 byte serial number, suitable for matching against an EEPROM's system serial. Note
+that this property is read-only.
+
+### rom property
+
+Returns a `NaomiRom` instance that encapsulates the ROM passed into the patcher. This
+instance should not be edited, as it will not be read again when performing the patches.
+Note that this property is read-only.
+
+### has_eeprom property
+
+Returns `True` if the ROM passed into the patcher has an attached EEPROM file. Returns
+`False` otherwise.
+
+### eeprom_info property
+
+Returns an optional instance of NaomiSettingsInfo if the ROM has a configured EEPROM
+section. If the ROM does not have a configured EEPROM section, this returns `None`.
+The NaomiSettingsInfo instance represents the configuration passed to `put_eeprom()`
+on a previous invocation. Note that this property is read-only.
+
+### get_eeprom() method
+
+Returns a 128-byte EEPROM bytestring that was previously attached to the Naomi ROM,
+or `None` if this ROM does not include any EEPROM settings.
+
+### put_eeprom() method
+
+given a bytes "eeprom" argument which is a valid 128-byte EEPROM, ensures that it
+is attached to the Naomi ROM such that the settings are written when netbooting the
+ROM image. If there are already EEPROM settings attached to the ROM, this overwrites
+those with new settings. If there are not already settings attached, this does the
+work necessary to attach the settings file as well as the writing trojan supplied to
+the `NaomiSettingsPatcher` constructor.
+
+Valid EEPROM files can be obtained form a number of places. If you use an emulator
+to set up system and game settings, then the EEPROM file that emulator writes can
+usually be supplied here to make your game boot to the same settings. If you use
+the `NaomiEEPRom` class to manipulate an EEPROM, the data it produces can also be
+supplied here to force the Naomi to use the same settings.
+
+Optionally, pass in the boolean keyword argument "enable_sentinel" set to True and
+the Naomi ROM will re-initialize the settings when netbooting even if the last game
+netbooted was this game. Use this when iterating over settings that you want to choose
+so that you can ensure the settings are written. If you do not provide this argument,
+the default behavior is that settings will not be overwritten when we netboot a game
+that is already running on the system.
+
+Optionally, pass in the boolean keyword argument "enable_debugging" set to True
+which forces the Naomi to display debugging information on the screen before booting
+the game. Use this to see what is actually going on under the hood when using the
+settings patching feature.
+
+Optionally, pass in the boolean keyword argument "verbose" set to True which forces
+the `put_eeprom()` function to output progress text to stdout. Use this if you are
+making a command-line tool and wish to display information about the patch process
+to the user.
+
+### has_sram property
+
+Returns `True` if the ROM passed into the patcher has an attached SRAM file. Returns
+`False` otherwise.
+
+### get_sram() method
+
+Returns a 32k-byte SRAM bytestring that was previously attached to the Naomi ROM, or
+`None` if this ROM does not include any SRAM settings.
+
+### put_sram() method
+
+given a bytes "settings" argument which is a valid 32k-byte SRAM, ensures that it is
+attached to the Naomi ROM such that the settings are written when netbooting the ROM
+image. If there are already SRAM settings attached to the ROM, this overwrites those
+with new settings. If there are not already settings attached, this does the work
+necessary to attach the settings file.
+
+Valid SRAM files can be obtained from an emulator that is capable of writing an SRAM
+file. This only makes sense to use in the context of atomiswave conversions and in
+a select few Naomi games that store their settings in SRAM such as Ikaruga.
+
+Optionally, pass in the boolean keyword argument "verbose" set to True which forces
+the `put_settings()` function to output progress text to stdout. Use this if you are
+making a command-line tool and wish to display information about the patch process
+to the user.
+
+# naomi.settings
+
+Collection of routines written in Python for safe manipulation of 128-byte
+Naomi EEPROM files using supplied system definition files. Essentially, given
+a valid 128-byte EEPROM or a valid 4-byte Naomi ROM serial and a set of system
+and game definition files, `naomi.settings` will provide you a high-level
+representation of valid settings including their defaults, valid values and
+relationships to each other. Settings editors can be built using this module
+which work together with `naomi.NaomiEEPRom` and `naomi.NaomiSettingsPatcher`
+to make the settings available when netbooting a game on a Naomi system.
+
+## Setting
+
+A single setting, with its name, default, current value, possible allowed values,
+and any possible relationship to other settings. Note that any relationship,
+if it exists, will only be to other Setting objects inside a `Settings` class.
+Note that you should not attempt to construct an instance of this yourself.
+You should only work with previously-constructed instances of it as found inside
+an instance of `Settings`.
+
+### name property
+
+The name of this setting, as a string. This is what you should display to a user
+if you are developing a settings editor.
+
+### order property
+
+The order that this setting showed up in the definition file that created it.
+Note that if you are implementing an editor, you can safely ignore this as the
+settings will already be placed in the correct display order.
+
+### size property
+
+The size of this setting, as an instance of SettingSizeEnum. The valid values
+for this are `SettingSizeEnum.NIBBLE` and `SettingSizeEnum.BYTE`. Note that if
+you are developing an editor, you can safely ignore this as the `values` property
+will include all valid values that this setting can be set to. You do not have to
+understand or manipulate this in any way and it is only present so that other
+parts of the `naomi.settings` module can do their job properly.
+
+### length property
+
+The length in bytes this setting takes up, if the `size` property is `SettingSizeEnum.BYTE`.
+If the `size` property is instead `SettingSizeEnum.NIBBLE` then this will always
+be set to 1. Note that much like the `size` property if you are implementing an
+editor you can safely ignore this property for the same rationale as above.
+
+### read_only property
+
+Whether this property is read-only or not. Some settings are not modifiable, such
+as the system serial number. Other settings are only modifiable if other settings
+are set to some value, such as the "Continue" setting on Marvel vs. Capcom 2 which
+is dependent on "Event" mode being off. If this property is "False" then this setting
+is user-editable under all circumstances. If this property is "True" then this setting
+is never user-editable. If this property is an instance of `ReadOnlyCondition` then
+it depends on some other settings for whether it is read-only. You can call the
+`evaluate()` method on the instance of `ReadOnlyCondition` which takes a list of
+`Setting` objects (this setting's siblings as found in a `Settings` object) and returns
+a boolean. If that boolean is "True", then this setting is currently read-only because
+of some other setting's value. If the boolean is "False", then the setting is currently
+editable because of some other setting's value.
+
+In the Naomi Test Mode, settings that are always read-only are hidden completely from
+the user. Settings which are never read-only are displayed to the user. And settings
+which are conditionally read-only will be conditionally hidden based on whether they
+are read-only. It is recommended that your editor perform a similar thing when you
+display settings. Settings whose `read_only` property is "False" should always be
+displayed. Settings whose `read_only` property is "True" should be completely hidden
+from the user. Settings whose `read_only` property is a `ReadOnlyCondition` should be
+evaluated and then the setting either grayed out when it is "True" or conditionally
+hidden from the user.
+
+### values property
+
+A dictionary whose keys are integers which the `current` property could be set
+to, and whose values are the strings which should be displayed to the user for
+those value selections. Note that if a setting is always read-only this may instead
+be None. It is guaranteed to be a dictionary with at least one value whenever a
+setting is user-editable.
+
+### current property
+
+The current integer value that the setting is set to. In order to display the correct
+thing to a user, you should use this as a key into the `values` property to look up
+the correct string to display.
+
+### default property
+
+The default value for this setting. Note that under some circumstances, this may
+not be available and will return None. You can safely ignore this property if you are
+developing an editor. If you wish to provide a "defaults" button in your editor, it
+is recommended to instead use the `from_serial()` or `from_rom()` method on an instance of
+`SettingsManager` which will return you a new `SettingsWrapper` with default values.
+This will correctly handle system and game defaults as well as dependendent default
+settings.
+
+## Settings
+
+A class which represents a collection of settings that can be used to manipulate
+a section of an EEPROM file. Note that you should not attempt to construct
+this yourself. You should only work with previously-constructed instances of
+it as found inside an instance of `SettingsWrapper`.
+
+### filename property
+
+The name of the settings definition file that was used to create this collection.
+Note that this is not a fully qualified path, but instead just the name of
+the file, like "system.settings" or "BBG0.settings". If you wish to look up
+the actual file location given this property, use the `files` property on an
+instance of `SettingsManager`.
+
+### type property
+
+An instance of SettingType which specifies whether this collection of settings
+is a system settings section or a game settings section in an EEPROM. Valid
+values are `SettingType.SYSTEM` and `SettingType.GAME`.
+
+### settings property
+
+A python list of `Setting` objects, representing the list of settings that
+can be mofidied or displayed. You should not assign to this property directly
+when modifying settings in a settings editor you are implementing. However,
+you are welcome to modify the properties of each setting in this list directly.
+
+### length property
+
+An integer representing how many bytes long the section of EEPROM represented
+by this collection is. For system settings, this will always be 16 since the
+system section is hardcoded at 16 bytes. For game settings, this will be
+determined by the settings definition file that was looked up for the game
+in question.
+
+## SettingsWrapper
+
+A class whose sole purpose is to encapsulate a group of system settings,
+game settings and the serial number of the game that the system and game
+settings go with. This is returned by many methods in `SettingsManager`
+and taken as a parameter of several more methods in `SettingsManager.
+
+Note that you should not attempt to construct this yourself. You should
+only work with previously-constructed instances of it as returned by
+methods in `SettingsManager`.
+
+### serial property
+
+The 4-byte serial of the game this `SettingsWrapper` instance has been
+created for.
+
+### system
+
+A collection of settings that manipulate the system section of the EEPROM
+for the game this instance has been created for. This is inside of a
+`Settings` wrapper object.
+
+### game
+
+A collection of settings that manipulate the game section of the EEPROM
+for the game this instance has been created for. This is inside of a
+`Settings` wrapper object.
+
+### to_json() method
+
+Converts the current instance of `SettingsWrapper` to a dictionary suitable
+for passing to `json.dumps`. This is provided as a convenience wrapper so
+that if you are implementing a web interface you don't have to serialize
+anything yourself. To unserialize a dictionary that you get from this method,
+call the `from_json` method on an instance of `SettingsManager`.
+
+## SettingsManager
+
+The `SettingsManager` class manages the ability to parse a 128-byte EEPROM
+file given a directory of settings definitions. It is responsible for
+identifying the correct files for patching given an EEPROM or ROM serial.
+It is also responsible for taking a modified list of settings and writing
+a new EEPROM file.
+
+Note that default definitions are included with this module. To grab the
+default definitions directory, use the `get_default_settings_directory` function
+which will return a fully qualified path to the settings directory of this
+module.
+
+Note that since this is parsing user-supplied settings definitions files,
+there can be errors in processing those files. In any function that returns
+a `SettingsWrapper` instance, a `SettingsParseException` can be thrown.
+This is a subclass of `Exception` so you can get the error message to
+display to a user by calling `str()` on the exception instance. The instance
+will also have a `filename` property which is the filename of the settings
+definition file that caused the problem.
+
+There can also be problems in saving EEPROM settings given the same definitions
+files. In this case, a `SettingsSaveException` can be thrown. This is identical
+to `SettingsParseException` save for the source, so all of the above documentation
+applies.
+
+There can also be problems in deserializing JSON data when calling the
+`from_json()` method. In this case, a `JSONParseException` can be thrown. Similar
+to the above two exceptions, calling `str()` on the instance will give you back
+an error message that can be displayed to a user. The instance will also have
+a `context` property which is the exact location in the JSON where the failure
+occured as represented by a list of attributes that were dereferenced in the
+JSON to get to the section that had an error.
+
+### Default Constructor
+
+Takes a single string argument "directory" which points at the directory
+which contains settings definition files and returns an instance of the
+`SettingsManager` class. In this repository, that directory is
+`naomi/settings/definitions/`. Note that the settings definitions in this
+repository can be found by using the `get_default_settings_directory` function.
+An example of how to initialize this is as follows:
+
+```
+from naomi.settings import get_default_settings_directory, SettingsManager
+
+dir = get_default_settings_directory()
+man = SettingsManager(dir)
+```
+
+### files property
+
+An instance of `SettingsManager` has the "files" property, which returns
+a dictionary of recognized settings definitions in the directory supplied to
+the default constructor. The returned dictionary has keys representing the
+settings definition file, such as "system.settings" or "BBG0.settings". The
+values of the dictionary are fully qualified system paths to the file in
+question.
+
+### from_serial() method
+
+Takes a single bytes argument "serial" as retrieved from Naomi ROM header
+and uses that to construct a `SettingsWrapper` class representing the
+available settings for a game that has the serial number provided. This
+can be used when you want to edit settings for a game but do not have an
+EEPROM already created. This will read the definitions files and create
+a `SettingsWrapper` with default settings. This can be then passed to the
+`to_eeprom()` function to return a valid 128-byte EEPROM representing the
+default settings.
+
+### from_rom() method
+
+Takes a NaomiRom instance argument "rom" and a NaomiRomReginEnum argument
+"region" and retrieves any requested system defaults from the Naomi ROM
+header. It uses that as well as the game's settings definition file to create
+a default EEPROM that is then used to construct a `SettingsWrapper` class
+repressenting the default settings as a Naomi would create them on first
+boot. This can then be edited or passed to the `to_eeprom()` function to
+return a valid 128-byte EEPROM representing the edited settings.
+
+### from_eeprom() method
+
+Takes a single bytes argument "data" as loaded from a valid 128-byte
+EEPROM file or as grabbed from the `data` property of an instance of
+`NaomiEEPRom` and constructs a `SettingsWrapper` class representing the
+available settings for a game that matches the serial number provided in
+the EEPROM file. This can be used when you want to edit the settings for
+a game and you already have the EEPROM file created. This will read the
+definitions file and parse out the current settings in the EEPROM and
+return a `SettingsWrapper` with those settings. This can then be modified
+and passed to the `to_eeprom()` function to return a valid 128-byte EEPROM
+representing the current settings.
+
+### from_json() method
+
+Takes a single dictionary argument "jsondict" and deserializes it to
+a `SettingsWrapper` instance. The dictionary argument can be retrieved
+by calling the `to_json()` method on an existing `SettingsWrapper` instance.
+This is provided specifically as a convenience method for code wishing to
+provide web editor interfaces. A recommended workflow is to create an
+instance of `SettingsManager`, request a `SettingsWrapper` by calling
+either `from_eeprom()` or `from_serial()` as appropriate, calling `to_json()`
+on the resulting `SettingsWrapper` class and then passing that to
+`json.dumps` to get valid JSON that can be sent to a JS frontend app. After
+the frontend app has manipulated the settings by modifying the current
+value of each setting, you can use `json.loads` to get back a dictionary
+that can be passed to this function to get a deserialized `SettingsWrapper`
+class. The deserialized `SettingsWrapper` instance can then be passed to
+the `to_eeprom()` function to return a valid 128-byte EEPROM representing
+the settings chosen by the JS frontend.
+
+### to_eeprom() method
+
+Given an instance of `SettingsWrapper` returned by either `from_serial()`,
+`from_eeprom()` or `from_json()`, calculates and returns a valid 128-byte
+EEPROM file that represents the settings. Use this when you are finished
+modifying system and game settings using code and wish to generate a valid
+EEPROM file that can be modified with `NaomiEEPRom`, placed in an emulator's
+data directory to load those settings or attached to a Naomi ROM using the
+`naomi.NaomiSettingsPatcher` class so that the settings are written when
+netbooting the rom on a Naomi system.
+
+# Settings Definitions Format
+
+Settings definition files are meant to be simple, human readable documentation
+for a game's EEPROM settings. They are written in such a way that on top of
+being human-readable documentation, they can also be parsed by
+`naomi.settings.SettingsManager` to help with making settings editors for any
+game on the Naomi platform. Each setting in a settings definition file represents
+how to parse some number of bytes in a game's EEPROM. You'll notice that while
+there is a size specifier for each setting there is no location specifier. That's
+because each setting is assumed to come directly after the previous setting in
+the section.
+
+All settings sections in an game's EEPROM are assumed to be little-endian, much
+like the Naomi system itself. Defaults and valid values are specified as hex
+digits as copied directly out of a hex editor. When specifying half-byte settings,
+the first setting is assumed to be the top half of the byte (the first hex digit
+that appears when reading the EEPROM in a hex editor) and the second setting is
+assumed to be the bottom half of the byte. All half-byte settings are expected
+to come in pairs.
+
+Aside from the "system.settings" file, all settings files are named after the
+serial number of the game they are associated with. The serial number for the
+game can be found by looking at the ROM header using a tool such as `rominfo`,
+or by looking at bytes 3-7 of an EEPROM that you got out of an emulator and
+loaded into a hex editor.
+
+The only necessary parts of a setting are the name and the size. If the setting
+is user-editable, there should be at least one valid value that the setting is
+allowed to be. Optionally, you can specify the default value for any setting
+and whether the setting is read-only. Additionally, read-only and default values
+can depend on the value of another setting.
+
+Settings are defined by writing any valid string name followed by a colon. Setting
+parts come after the colon and are either comma-separated or are placed one per
+line after the setting name. You can mix and match any number of comma-separated
+parts and parts on their own lines. Whatever makes the most sense and is the most
+readable is allowed. Settings parts can show up in any order after the setting
+name. You can define size, read-only, defaults and valid options in any order you
+wish. The only restriction is that the size part MUST appear before any default parts.
+
+Any line in a settings definition file that starts with a hashtag (`#`) is treated
+as a comment. You can write anything you want in comments so feel free to write
+down any useful information about settings you think somebody else might care to
+know.
+
+## A Simple Setting
+
+The most basic setting is one that has a name, a size and some allowed values.
+An example of such a setting is like so:
+
+```
+Sample Setting: byte, values are 1 to 10
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. Editors that
+display this setting will display a drop-down or selection box that includes
+the decimal values "1", "2", "3", "4", "5", "6", "7", "8", "9", and "10".
+The decimal values for each valid setting is automatically inferred based on
+the range given in the setting.
+
+If you want to specify some alternate text for each valid setting, you may
+do so like so:
+
+```
+Sample Setting: byte, 1 - On, 0 - Off
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01 and 00 applied to it. Editors that display this setting
+will display a drop-down or selection box that includes the value "On" and
+"Off" and will select the correct one based on the value in the EEPROM when it
+is parsed.
+
+You can mix and match how you define settings values if it is most convenient.
+For example, the following setting mixes the two ways of specifying valid
+values:
+
+```
+Sample Setting: byte, 0 - Off, 1 to 9, 10 - MAX
+```
+
+This defines a setting named "Sample Setting" which is a single byte and
+can have the hex values 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. Editors
+that display this setting will display a drop-down or selection box that includes
+the options "Off", "1", "2", "3", "4", "5", "6", "7", "8", "9", "MAX". The
+correct one will be selected based on the value in the EEPROM when it is parsed.
+
+## Changing the Setting Display
+
+Normally, if you have some number of values that a setting can be and you
+want to control what an editor displays when selecting each value, you would
+list each value out individually along with the text it should be displayed as.
+However, if you have a large range of values and you want to display them in
+hex instead of decimal, you can instead do the following:
+
+```
+Sample Setting: byte, values are 1 to 10 in hex
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. This is identical
+to the simple setting in the previous section. However, editors that display this
+setting will display a drop-down or selection box that includes the options
+"01", "02", "03", "04", "05", "06", "07", "08", "09" and "0a". You could have
+written the settings out individually, but for large ranges that you want to
+display in hex this is faster.
+
+## Changing the Setting Size
+
+If your setting spans more than 1 byte, or it is only the top half or bottom
+half of a byte, you can specify that in the size part. For settings that occupy
+more than 1 byte, you can simply write the number of bytes in the part section.
+If a setting only occupies the top or bottom half of a byte, you can specify
+a half-byte for the size.
+
+An example of a setting that takes up 4 bytes is as follows:
+
+```
+Big Setting: 2 bytes, 12 34 - On, 56 78 - Off
+```
+
+This defines a setting named "Big Setting" that takes up two bytes and has
+the two hex values 12 34 and 56 78 as read in a hex editor as its options.
+Editors will display either "On" or "Off" as they would for 1 byte settings.
+
+An example of a pair of settings that take up half a byte each is as follows:
+
+```
+Small Setting 1: half-byte, values are 1 to 2
+Small Setting 2: half-byte, values are 3 to 4
+```
+
+This defines two settings named "Small Setting 1" and "Small Setting 2". Each
+setting takes up half a byte. The first setting, "Small Setting 1", will take
+the top half of the byte, and the second, "Small Setting 2", will take the
+bottom half of the byte. The hex values for each are the same as they would
+be for all other documented settings. Note that the settings came in a pair
+because you have to specify both halves of the byte!
+
+## Specifying Read-Only Settings
+
+Sometimes there is a setting that you can't figure out, or there's a setting
+that the game writes when it initializes the EEPROM but never changes. In this
+case you can mark the setting read-only and editors will not let people see
+or change the setting. However, the setting will still be created when somebody
+needs to make a default EEPROM based on the settings definition file.
+
+An example of how to mark a setting as read-only:
+
+```
+Hidden Setting: byte, read-only
+```
+
+In this case, there is a setting named "Hidden Setting" which is a single
+byte. We specified that it was read-only, so editors will not display the
+setting to the user. Also, since it was read-only, we didn't need to specify
+any allowed values. You can use this when there are parts of the EEPROM you
+don't want people to mess with, or that you don't understand so you just need
+to skip it.
+
+Sometimes there are settings that only display in some scenarios, such as when
+another setting is set to a certain value. If you run into a setting such as
+this, you can specify that relationship like so:
+
+```
+Sometimes Hidden Setting: byte, read-only if Other Setting is 1, values are 0 to 2
+```
+
+This defines a setting called "Sometimes Hidden Setting" which is a single byte
+and can have the hex values 00, 01 and 02. When another setting named "Other
+Setting" is set to 1, this setting becomes read-only and cannot be modified
+by the user. When that other setting named "Other Setting" is set to any other
+value, this setting becomes user-changeable.
+
+If you want to specify that a setting is read-only unless another setting is
+a certain value, you can do so like the following:
+
+```
+Sometimes Hidden Setting: byte, read-only unless Other Setting is 1, values are 0 to 2
+```
+
+This defines the same setting as the first example, but the read-only logic
+is reversed. This setting will be read-only when "Other Setting" is any value
+but 1, and will be user-changeable when "Other Setting" is 1.
+
+If you need to specify multiple values for the other setting, you can do so
+like so:
+
+```
+Sometimes Hidden Setting: byte, read-only if Other Setting is 1 or 2, values are 0 to 2
+```
+
+This defines the same setting as the first example, but the read-only logic
+is changed. The setting will be read only when "Other Setting" is 1 or 2, and
+will be user-changeable when "Other Setting" is any other value.
+
+## Specifying Defaults
+
+Its nice to specify what the default for each setting is. This way, editors
+can make a new EEPROM from scratch for the game you are defining without needing
+an EEPROM to exist first. If you don't specify a default, the default for the
+setting is assumed to be 0. If that isn't a valid value for a setting, you'll
+run into problems so it is best to define defaults for settings when you can.
+
+To specify a default, you can do the following:
+
+```
+Default Setting: byte, default is 1, values are 1, 2
+```
+
+This defines a setting named "Defaut Setting" which is a single byte and whose
+valid values are 01 and 02. The default value when creating an EEPROM from
+scratch is 01.
+
+If a setting is read-only, then when we an EEPROM is edited and saved, the
+default value will take precidence over the current value. If a setting is
+user-editable, then the current value will take precidence over the default
+value. This is so that you can have settings which are optionally read-only
+based on other settings and specify what value the setting should be when
+it is read-only. This isn't often necessary but it can come in handy in some
+specific scenarios.
+
+For example, in Marvel Vs. Capcom 2, the "Continue" setting is defaulted to
+"On". However, if event mode is turned on, then the "Continue" setting is
+forced to "Off" and becomes no longer user-editable. To represent such
+a case as this, you can do something like the following:
+
+```
+Event: byte, default is 0
+ 0 - Off
+ 1 - On
+Continue: byte, read-only if Event is 1, default is 1 if Event is 0, default is 0 if Event is 1
+ 0 - Off
+ 1 - On
+```
+
+This can be a bit daunting to read at first, so let's break it down. First,
+it defines a setting named "Event" which is a byte and can have values 00 and 01.
+Those values are labelled "Off" and "On" respectively. Event mode is off by default.
+Then, it defines a setting named "Continue" which is a byte as well. It has values
+00 and 01 labelled "Off" and "On" respectively. It is user-editable when event mode
+is off, and it is read-only when event mode is on. When event mode is off, the default
+is 01, which corresponds to "On". When event mode is on, the default is "00" which
+corresponds to "Off". Remember how settings that are read-only try to save the
+default first, and settings that are user-changeable try to save the current value
+first? That's where the magic happens. When the "Event" setting is set to "On"
+then the "Continue" setting is read-only, so we will save the default hex value of 00!
+When the "Event" setting is set to "Off", the "Continue" setting is user-changeable so
+we will save whatever value the user selected! When we create a new EEPROM from scratch,
+we set "Event" to 00 which tells the "Continue" setting to default to 01. It all works
+perfectly!
+
+### Specifying Entirely-Dependent Defaults
+
+Sometimes you might run into a setting that seems to be identical to another setting,
+or a setting that seems to be the same as another setting plus or minus some adjustment
+value. If you encounter such a relationship, you can represent it by doing something
+like the following:
+
+```
+Setting: byte, default is 0, values are 1 to 10
+Dependent Setting: byte, read-only, default is value of Setting
+```
+
+This defines a setting named "Setting" which is a single byte that can have hex values
+01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. It defines a second setting named "Dependent
+Setting" which defaults to whatever "Setting" is set to. Since it is read-only, the
+default will take precidence over the current value, so when somebody edits "Setting"
+in an editor, both "Setting" and "Dependent Setting" will be saved with the same value!
+
+In some cases, a setting will be dependent on another setting, but won't have the
+exact same value. If you wanted to, you could list out a whole bunch of default conditionals
+to represent all of the possibilities, like so:
+
+```
+Setting: byte, default is 0, values are 1 to 3
+Dependent Setting: byte, read-only
+ default is 0 if Setting is 1
+ default is 1 if Setting is 2
+ default is 2 if Setting is 3
+```
+
+This would work, and sets up "Dependent Setting" to be 00 when Setting is 01, 01 when
+Setting is 02, and 02 when Setting is 03. However, if there are a lot of possible values
+for "Setting", this can get tedious. Instead, you can represent the relationship like so:
+
+```
+Setting: byte, default is 0, values are 1 to 3
+Dependent Setting: byte, read-only, default is value of Setting - 1
+```
+
+This defines the exact same pair of settings, with the exact same defaults!
+
+## Specifying an Alternate Display Order
+
+Normally settings are displayed in exactly the order the show up in the
+file. Sometimes settings show up in a different order in a game's test
+menu than they appear in the EEPROM file itself. You can't just rearrange
+the order that the settings appear in the definition file since that
+dictates the order that the settings themselves are processed. So, instead
+you can specify that a setting should be displayed before or after another
+setting. Here is an example:
+
+```
+Simple Setting: byte, values are 1 to 10
+Other Setting: byte, values are 2 to 5, display before Simple Setting
+```
+
+This defines two settings named "Simple Setting" and "Other Setting". While
+"Simple Setting" comes first when parsing the EEPROM itself, when it comes
+time to display the settings in an editor, "Other Setting" will be displayed
+first and then "Simple Setting".
+
+Similarly, you can specify that a setting come after another setting like so:
+
+```
+Simple Setting: byte, values are 1 to 10, display after Other Setting
+Other Setting: byte, values are 2 to 5
+```
+
+Both the above examples produce the exact same list of settings in an editor.
+
+## Using ":" or "," in Setting Names or Values
+
+Since these are special characters used to figure out where a setting name ends
+as well as separate sections, using one of these characters in a setting name or
+value description will result in an error. In order to have a setting that
+includes one of these symbols, you can escale it like so:
+
+```
+Setting With A Colon\: The Revengence: byte, 1 - Good\, Very Good, 2 - Bad\, Very Bad
+```
+
+This defines a setting named "Setting With a Colon: The Revengence" that has two
+labelled values consisting of "Good, Very Good" and "Bad, Very Bad". Whenever you
+need to use a character that is special, prefix it with a "\\". This includes the
+"\\" character as it denotes that the next character should be escaped. So if you
+want a "\\" character in your setting name or value, you should use two "\\" characters
+in a row.
+
+
+%package -n python3-naomiutils
+Summary: Code libraries for working with Naomi ROMs and EEPROMs.
+Provides: python-naomiutils
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-naomiutils
+# naomi
+
+Collection of routines written in Python for manipulating Naomi ROM and EEPROM
+files. This is geared towards enthusiasts building their own netboot servers or
+RPI setups and provides libraries for examining ROM and manipulating ROM headers
+as well as attaching EEPROM settings to ROM files and manipulating their contents.
+It is fully typed and requires a minimum of Python 3.6 to operate.
+
+## NaomiEEPRom
+
+The NaomiEEPRom class provides high-level accessors to a 128-byte Naomi EEPROM
+dump as obtained through a ROM dumper or from an emulator's saved state. It handles
+correcting various CRCs as well as allowing high-level access to the duplicated
+game and system settings sections. Use this to create or manipulate a raw EEPROM
+data file.
+
+### Default Constructor
+
+Takes a single byte argument "data" and verifies that it is a valid 128-byte EEPROM
+before returning an instance of the `NaomiEEPRom` class used to manipulate that
+data. If any of the CRCs do not match this will raise a `NaomiEEPRomException`.
+
+### NaomiEEPRom.default
+
+An alternate constructor that takes a single byte argument "serial" and an optional
+byte argument "game_defaults" and creates a valid EEPROM based on this data, returning
+an instance of the `NaomiEEPRom` class that can be used to manipulate this newly
+created EEPROM. The serial argument should be exactly bytes and begin with a "B",
+followed by two characters and finally a digit, as represented by a bytestring. This
+is a Naomi system restriction. Optionally, a string of bytes can be given in the
+"game_defaults" section which will be used to determine the length and default
+values of the game section of the EEPROM.
+
+### NaomiEEPRom.validate
+
+A static method that takes a byte argument "data" and checks it for validity. This
+includes making sure the length is 128 bytes and that all CRCs are correct. Optionally
+you can pass in the boolean keyword argument "only_system" set to True to only check
+that the system section is valid. This is useful for validating EEPROMs where the BIOS
+has written system settings but the game has not yet booted and created its own
+defaults yet. You can use this function to ensure that passing data to the default
+constructor will not result in an exception.
+
+### data property
+
+An instance of NaomiEEPRom has the "data" property, which returns a bytes object
+representing the current 128-byte EEPROM. This will have all CRC sections fixed.
+Use the "data" property to retrieve the EEPROM for writing to a file or sending to
+a Naomi system after manipulating data using the NaomiEEPRom class. Note that this
+is read-only, you should not attempt to manipulate the raw data using this property.
+
+## serial property
+
+Returns the 4 byte serial that is found in the system section of the EEPROM. This
+will match a serial given in the `NaomiEEPRom.default` constructor when it is used.
+Use this to help determine what game an EEPROM goes with. Note that this is read-only.
+To modify the serial, create a new EEPROM with that serial. Game settings and system
+settings are not compatible across games on the Naomi platform.
+
+## length property
+
+The length in bytes as an integer of the game section of the EEPROM. If the game section
+is not valid this return 0 bytes. Otherwise it returns the length of the game section
+itself. This property is writeable. If you provide it a new value, the game section
+will be resized to that length. Use this to determine the bounds of the `game` section
+as documented below, as well as to resize the `game` section.
+
+## system property
+
+Returns a bytes-like wrapper object representing the system section of the EEPROM.
+This operates like a bytearray object in Python. That means you can access or mutate
+any byte or section in the system area using this property. Note that this wrapper
+object takes care of reading from and writing to both mirrors of the system section in
+the EEPROM file as well as ensuring that the CRC is correct. Note also that the system
+section is hard-coded to 16 bytes in length which cannot be modified. This is a system
+restriction on the Naomi platform. Much like bytes objects in python, accessing a single
+byte returns an integer in the range of 0-255, but accessing a range returns a bytes
+object.
+
+A simple example of reading bytes 6-8 of the system section:
+
+```
+eeprom = NaomiEEPRom(somedata)
+print(eeprom.system[6:8]) # Will print a bytes object of length 2.
+```
+
+A simple example of writing bytes 10-12 of the system section:
+
+```
+eeprom = NaomiEEPRom(somedata)
+eeprom.system[10:12] = b"\x12\x34"
+```
+
+## game property
+
+Returns a bytes-like wrapper object representing the game section of the EEPROM. This
+operates identically to the `system` property as documented above, only it accesses the
+game section of the EEPROM. Note that for this to work properly, the game section needs
+to be initialized by setting the `length` property on the instance of `NaomiEEPRom`. If
+you are manipulating an existing EEPROM file, this property will already be set for you.
+
+Note that this wrapper object includes a `valid` property which returns if the current
+section is valid in the EEPROM you are manipulating. This will always be `True` for
+the system section. However, if you access the game section on a newly-created EEPROM
+without setting defaults or a length, the game property's `valid` property will return
+`False`.
+
+An example of verifying that the game section is valid:
+
+```
+eeprom = NaomiEEPRom.default(serial=b"BBG0")
+print(eeprom.game.valid) # Will print "False" as the EEPROM was created without a game section default.
+eeprom.length = 20
+print(eeprom.game.valid) # Will print "True" as the EEPROM game section was initialized to be 20 bytes long.
+```
+
+## NaomiRom
+
+The NaomiRom class provides high-level accessors to a Naomi ROM header as found
+at the beginning of a ROM file suitable for netbooting. It handles decoding all
+sections of the ROM header as well as allowing modification and even creation of
+new ROM header sections given valid data. Use this if you wish to manipulate or
+create your own Naomi ROM files form scratch.
+
+### Default Constructor
+
+Takes a single byte argument "data" and uses it as the ROM image where the header
+will be extracted. Note that there is no CRC over the ROM header so any data that
+is 1280 bytes or longer will appear valid.
+
+### NaomiRom.default
+
+An alternate constructor that creates an entirely blank Naomi ROM containing no
+loaded executable or test sections and no ROM name. Use this when you want to
+programatically construct a ROM image, such as when you are building a final ROM
+in a homebrew program you are building for the Naomi platform.
+
+### valid property
+
+An instance of NaomiRom has the "valid" property which will be "True" when the ROM
+passed into the constructor is a valid Naomi ROM and "False" otherwise. This is a
+read-only property as the vailidity of a ROM is entirely dictated by the data
+passed into the constructor.
+
+### data property
+
+The ROM data, as passed into the constructor for the instance of NaomiRom, or as
+created when using `NaomiRom.default` alternate constructor. Note that when any
+of the following properties are written, the `data` property will be changed to
+reflect those settings. Use this to retrieve the updated ROM after you've made
+adjustments to the values you wish to change.
+
+### publisher property
+
+The publisher of this ROM, as a string. When read, grabs the current publisher
+of the ROM image. When written, updates the publisher to the new string provided.
+
+### names property
+
+A dictionary of names indexed by region. Given the current system region, the names
+that show up here will also be the names that show up in the test menu for a given
+game. Note that there are the following constants that can be used to index into the
+names list: `NaomiRomRegionEnum.REGION_JAPAN`, `NaomiRomRegionEnum.REGION_USA`,
+`NaomiRomRegionEnum.REGION_EXPORT`, `NaomiRomRegionEnum.REGION_KOREA`, and finally
+`NaomiRomRegionEnum.REGION_AUSTRALIA`. Note that the last region, Australia, exists
+in many ROM files but is not accessible as there is no Australia BIOS for the Naomi
+platform. When read, grabs a dictionary of names of the ROM given the region. When
+written, updates the ROM names by region using the dictionary provided.
+
+### sequencetexts property
+
+A list of 8 sequence texts that are used by the game for coin insertion messages.
+Many ROMs only have the first sequence set. When read, grabs all 8 sequence texts
+and returns a list of them. When written, updates the sequence texts to the new
+list of strings provided.
+
+### defaults property
+
+A dictionary of NaomiEEPROMDefaults instance representing what defaults the BIOS will
+set in the system EEPROM section when initializing the EEPROM on first boot. Note
+that this is indexed by the same enumeration as the "names" property. When read, grabs
+the defaults and returns them. When written, extracts values from the provided
+NaomiEEPROMDefaults instances and updates the per-region defaults in the ROM accordingly.
+
+### date property
+
+A `datetime.date` instance representing what date the ROM was build and released.
+When read, returns the current date in the ROM header. When written, updates the
+date of the ROM with the new `datetime.date` provided.
+
+### serial property
+
+A 4-byte bytestring representing the serial number of the ROM. This is used to tie
+EEPROM data to the ROM itself and lets the Naomi know when to reset certain defaults.
+When read, returns the current serial from the ROM header. When written, updates the
+serial in the ROM header.
+
+### regions property
+
+A list of NaomiRomRegionEnum values representing valid regions this ROM will run under.
+Uses the same region constants as the `names` property. When read, returns a list of
+the valid regions this ROM executes under. When written, updates the list of regions
+the ROM is allowed to execute under. When booting, the Naomi BIOS will check the
+current region against this list and show an error if the current region is not
+included in the list.
+
+### players property
+
+A list of integers representing the valid number of player configurations that this
+ROM will boot under. Valid player numbers include 1, 2, 3 and 4. When read, returns
+a list of all valid number of player configurations that this game will boot with.
+When written, updates the list of player configurations. When booting, the Naomi
+BIOS will check the "Number of Players" setting in the system assignments and see
+if that setting appears in this list.
+
+### frequencies property
+
+A list of frequencies that the monitor is allowed to run at for this ROM. This
+includes the values 15 and 31. On read, returns the list of allowed frequencies.
+On write, updates the list of allowed frequencies. On boot, the Naomi BIOS will
+check the current horizontal refresh rate of the system as controlled by a DIP
+switch and show an error if it isn't in the list of allowed frequencies.
+
+### orientations property
+
+A list of strings representing the allowed orientations for the monitor for this
+ROM. The includes the values "horizontal" and "vertical". On read, returns the
+list of all acceptable orientations. On write, updates that list based on the
+provided list of strings. On boot, the Naomi BIOS will check the current "Monitor
+Orientation" setting in the system assignments and see if that orientation is
+on this list.
+
+### servicetype property
+
+A string value of either "individual" or "common" for the expected service button
+type for the ROM. On read, returns either "individual" or "common" to represent
+the current service type selected. On write, updates the service type to match
+the string provided.
+
+### main_executable property
+
+An instance of a NaomiExecutable including sections of the ROM that the Naomi
+BIOS will copy before executing the ROM, as well as the entrypoint in main RAM
+that the BIOS will jump to after copying sections. On read, returns the current
+list of sections to copy as well as the main entrypoint, as encapsulated as an
+instance of NaomiExecutable. On write, it updates the ROM to the new executable
+configuration by unpacking the NaomiExecutable instance given.
+
+### test_executable property
+
+This property is identical to the `main_executable` property, except for it
+represents the code and entrypoint that the Naomi BIOS will use when executing
+the "Game Test Mode" section of the test menu. It can be similarly read and written.
+
+## NaomiSettingsPatcher
+
+The NaomiSettingsPatcher class provides logic for attaching an EEPROM or SRAM configuration
+file to a Naomi ROM so that it can be written to the EEPROM/SRAM when netbooting that
+ROM. Note that this is not a supported feature of the Naomi platform, so it uses
+an executable stub that it attaches to the ROM in order to make this work. If you
+do not care what executable stub is attached and only want to patch settings into
+a ROM file, use the `get_default_trojan` function which will return a bytes
+object suitable for passing into a `NaomiSettingsPatcher` constructor.
+
+### Default Constructor
+
+Takes a bytes "rom" argument and a bytes "trojan" argument creates an instance of
+NaomiSettingsPatcher which can attach or retrieve previously-attached EEPROM or SRAM settings
+in a Naomi ROM file suitable for netbooting. An example of how to initialize this
+is as follows:
+
+```
+from naomi import NaomiSettingsPatcher, get_default_trojan
+
+patcher = NaomiSettingsPatcher(somedata, get_default_trojan())
+```
+
+### data property
+
+The same bytes as passed to the `NaomiSettingsPatcher` constructor. After calling
+`put_settings()` as documented below, this will be updated to the new ROM contents
+with the settings applied. A recommended workflow is to patch ROMs on-the-fly when
+netbooting by creating an instance of `NaomiSettingsPatcher` with the ROM data you
+were about to send, calling `put_settings()` with the settings you wish to attach,
+and then getting the data using this property and sending it down the wire to the
+Naomi system. Note that you can attach either an EEPROM file (128 bytes) or an SRAM
+file (32kb) but not both.
+
+### serial property
+
+An instance of NaomiSettingsPatcher has the `serial` property. When read, this
+will examine the serial of the Naomi ROM passed into the constructor and return the
+4 byte serial number, suitable for matching against an EEPROM's system serial. Note
+that this property is read-only.
+
+### rom property
+
+Returns a `NaomiRom` instance that encapsulates the ROM passed into the patcher. This
+instance should not be edited, as it will not be read again when performing the patches.
+Note that this property is read-only.
+
+### has_eeprom property
+
+Returns `True` if the ROM passed into the patcher has an attached EEPROM file. Returns
+`False` otherwise.
+
+### eeprom_info property
+
+Returns an optional instance of NaomiSettingsInfo if the ROM has a configured EEPROM
+section. If the ROM does not have a configured EEPROM section, this returns `None`.
+The NaomiSettingsInfo instance represents the configuration passed to `put_eeprom()`
+on a previous invocation. Note that this property is read-only.
+
+### get_eeprom() method
+
+Returns a 128-byte EEPROM bytestring that was previously attached to the Naomi ROM,
+or `None` if this ROM does not include any EEPROM settings.
+
+### put_eeprom() method
+
+given a bytes "eeprom" argument which is a valid 128-byte EEPROM, ensures that it
+is attached to the Naomi ROM such that the settings are written when netbooting the
+ROM image. If there are already EEPROM settings attached to the ROM, this overwrites
+those with new settings. If there are not already settings attached, this does the
+work necessary to attach the settings file as well as the writing trojan supplied to
+the `NaomiSettingsPatcher` constructor.
+
+Valid EEPROM files can be obtained form a number of places. If you use an emulator
+to set up system and game settings, then the EEPROM file that emulator writes can
+usually be supplied here to make your game boot to the same settings. If you use
+the `NaomiEEPRom` class to manipulate an EEPROM, the data it produces can also be
+supplied here to force the Naomi to use the same settings.
+
+Optionally, pass in the boolean keyword argument "enable_sentinel" set to True and
+the Naomi ROM will re-initialize the settings when netbooting even if the last game
+netbooted was this game. Use this when iterating over settings that you want to choose
+so that you can ensure the settings are written. If you do not provide this argument,
+the default behavior is that settings will not be overwritten when we netboot a game
+that is already running on the system.
+
+Optionally, pass in the boolean keyword argument "enable_debugging" set to True
+which forces the Naomi to display debugging information on the screen before booting
+the game. Use this to see what is actually going on under the hood when using the
+settings patching feature.
+
+Optionally, pass in the boolean keyword argument "verbose" set to True which forces
+the `put_eeprom()` function to output progress text to stdout. Use this if you are
+making a command-line tool and wish to display information about the patch process
+to the user.
+
+### has_sram property
+
+Returns `True` if the ROM passed into the patcher has an attached SRAM file. Returns
+`False` otherwise.
+
+### get_sram() method
+
+Returns a 32k-byte SRAM bytestring that was previously attached to the Naomi ROM, or
+`None` if this ROM does not include any SRAM settings.
+
+### put_sram() method
+
+given a bytes "settings" argument which is a valid 32k-byte SRAM, ensures that it is
+attached to the Naomi ROM such that the settings are written when netbooting the ROM
+image. If there are already SRAM settings attached to the ROM, this overwrites those
+with new settings. If there are not already settings attached, this does the work
+necessary to attach the settings file.
+
+Valid SRAM files can be obtained from an emulator that is capable of writing an SRAM
+file. This only makes sense to use in the context of atomiswave conversions and in
+a select few Naomi games that store their settings in SRAM such as Ikaruga.
+
+Optionally, pass in the boolean keyword argument "verbose" set to True which forces
+the `put_settings()` function to output progress text to stdout. Use this if you are
+making a command-line tool and wish to display information about the patch process
+to the user.
+
+# naomi.settings
+
+Collection of routines written in Python for safe manipulation of 128-byte
+Naomi EEPROM files using supplied system definition files. Essentially, given
+a valid 128-byte EEPROM or a valid 4-byte Naomi ROM serial and a set of system
+and game definition files, `naomi.settings` will provide you a high-level
+representation of valid settings including their defaults, valid values and
+relationships to each other. Settings editors can be built using this module
+which work together with `naomi.NaomiEEPRom` and `naomi.NaomiSettingsPatcher`
+to make the settings available when netbooting a game on a Naomi system.
+
+## Setting
+
+A single setting, with its name, default, current value, possible allowed values,
+and any possible relationship to other settings. Note that any relationship,
+if it exists, will only be to other Setting objects inside a `Settings` class.
+Note that you should not attempt to construct an instance of this yourself.
+You should only work with previously-constructed instances of it as found inside
+an instance of `Settings`.
+
+### name property
+
+The name of this setting, as a string. This is what you should display to a user
+if you are developing a settings editor.
+
+### order property
+
+The order that this setting showed up in the definition file that created it.
+Note that if you are implementing an editor, you can safely ignore this as the
+settings will already be placed in the correct display order.
+
+### size property
+
+The size of this setting, as an instance of SettingSizeEnum. The valid values
+for this are `SettingSizeEnum.NIBBLE` and `SettingSizeEnum.BYTE`. Note that if
+you are developing an editor, you can safely ignore this as the `values` property
+will include all valid values that this setting can be set to. You do not have to
+understand or manipulate this in any way and it is only present so that other
+parts of the `naomi.settings` module can do their job properly.
+
+### length property
+
+The length in bytes this setting takes up, if the `size` property is `SettingSizeEnum.BYTE`.
+If the `size` property is instead `SettingSizeEnum.NIBBLE` then this will always
+be set to 1. Note that much like the `size` property if you are implementing an
+editor you can safely ignore this property for the same rationale as above.
+
+### read_only property
+
+Whether this property is read-only or not. Some settings are not modifiable, such
+as the system serial number. Other settings are only modifiable if other settings
+are set to some value, such as the "Continue" setting on Marvel vs. Capcom 2 which
+is dependent on "Event" mode being off. If this property is "False" then this setting
+is user-editable under all circumstances. If this property is "True" then this setting
+is never user-editable. If this property is an instance of `ReadOnlyCondition` then
+it depends on some other settings for whether it is read-only. You can call the
+`evaluate()` method on the instance of `ReadOnlyCondition` which takes a list of
+`Setting` objects (this setting's siblings as found in a `Settings` object) and returns
+a boolean. If that boolean is "True", then this setting is currently read-only because
+of some other setting's value. If the boolean is "False", then the setting is currently
+editable because of some other setting's value.
+
+In the Naomi Test Mode, settings that are always read-only are hidden completely from
+the user. Settings which are never read-only are displayed to the user. And settings
+which are conditionally read-only will be conditionally hidden based on whether they
+are read-only. It is recommended that your editor perform a similar thing when you
+display settings. Settings whose `read_only` property is "False" should always be
+displayed. Settings whose `read_only` property is "True" should be completely hidden
+from the user. Settings whose `read_only` property is a `ReadOnlyCondition` should be
+evaluated and then the setting either grayed out when it is "True" or conditionally
+hidden from the user.
+
+### values property
+
+A dictionary whose keys are integers which the `current` property could be set
+to, and whose values are the strings which should be displayed to the user for
+those value selections. Note that if a setting is always read-only this may instead
+be None. It is guaranteed to be a dictionary with at least one value whenever a
+setting is user-editable.
+
+### current property
+
+The current integer value that the setting is set to. In order to display the correct
+thing to a user, you should use this as a key into the `values` property to look up
+the correct string to display.
+
+### default property
+
+The default value for this setting. Note that under some circumstances, this may
+not be available and will return None. You can safely ignore this property if you are
+developing an editor. If you wish to provide a "defaults" button in your editor, it
+is recommended to instead use the `from_serial()` or `from_rom()` method on an instance of
+`SettingsManager` which will return you a new `SettingsWrapper` with default values.
+This will correctly handle system and game defaults as well as dependendent default
+settings.
+
+## Settings
+
+A class which represents a collection of settings that can be used to manipulate
+a section of an EEPROM file. Note that you should not attempt to construct
+this yourself. You should only work with previously-constructed instances of
+it as found inside an instance of `SettingsWrapper`.
+
+### filename property
+
+The name of the settings definition file that was used to create this collection.
+Note that this is not a fully qualified path, but instead just the name of
+the file, like "system.settings" or "BBG0.settings". If you wish to look up
+the actual file location given this property, use the `files` property on an
+instance of `SettingsManager`.
+
+### type property
+
+An instance of SettingType which specifies whether this collection of settings
+is a system settings section or a game settings section in an EEPROM. Valid
+values are `SettingType.SYSTEM` and `SettingType.GAME`.
+
+### settings property
+
+A python list of `Setting` objects, representing the list of settings that
+can be mofidied or displayed. You should not assign to this property directly
+when modifying settings in a settings editor you are implementing. However,
+you are welcome to modify the properties of each setting in this list directly.
+
+### length property
+
+An integer representing how many bytes long the section of EEPROM represented
+by this collection is. For system settings, this will always be 16 since the
+system section is hardcoded at 16 bytes. For game settings, this will be
+determined by the settings definition file that was looked up for the game
+in question.
+
+## SettingsWrapper
+
+A class whose sole purpose is to encapsulate a group of system settings,
+game settings and the serial number of the game that the system and game
+settings go with. This is returned by many methods in `SettingsManager`
+and taken as a parameter of several more methods in `SettingsManager.
+
+Note that you should not attempt to construct this yourself. You should
+only work with previously-constructed instances of it as returned by
+methods in `SettingsManager`.
+
+### serial property
+
+The 4-byte serial of the game this `SettingsWrapper` instance has been
+created for.
+
+### system
+
+A collection of settings that manipulate the system section of the EEPROM
+for the game this instance has been created for. This is inside of a
+`Settings` wrapper object.
+
+### game
+
+A collection of settings that manipulate the game section of the EEPROM
+for the game this instance has been created for. This is inside of a
+`Settings` wrapper object.
+
+### to_json() method
+
+Converts the current instance of `SettingsWrapper` to a dictionary suitable
+for passing to `json.dumps`. This is provided as a convenience wrapper so
+that if you are implementing a web interface you don't have to serialize
+anything yourself. To unserialize a dictionary that you get from this method,
+call the `from_json` method on an instance of `SettingsManager`.
+
+## SettingsManager
+
+The `SettingsManager` class manages the ability to parse a 128-byte EEPROM
+file given a directory of settings definitions. It is responsible for
+identifying the correct files for patching given an EEPROM or ROM serial.
+It is also responsible for taking a modified list of settings and writing
+a new EEPROM file.
+
+Note that default definitions are included with this module. To grab the
+default definitions directory, use the `get_default_settings_directory` function
+which will return a fully qualified path to the settings directory of this
+module.
+
+Note that since this is parsing user-supplied settings definitions files,
+there can be errors in processing those files. In any function that returns
+a `SettingsWrapper` instance, a `SettingsParseException` can be thrown.
+This is a subclass of `Exception` so you can get the error message to
+display to a user by calling `str()` on the exception instance. The instance
+will also have a `filename` property which is the filename of the settings
+definition file that caused the problem.
+
+There can also be problems in saving EEPROM settings given the same definitions
+files. In this case, a `SettingsSaveException` can be thrown. This is identical
+to `SettingsParseException` save for the source, so all of the above documentation
+applies.
+
+There can also be problems in deserializing JSON data when calling the
+`from_json()` method. In this case, a `JSONParseException` can be thrown. Similar
+to the above two exceptions, calling `str()` on the instance will give you back
+an error message that can be displayed to a user. The instance will also have
+a `context` property which is the exact location in the JSON where the failure
+occured as represented by a list of attributes that were dereferenced in the
+JSON to get to the section that had an error.
+
+### Default Constructor
+
+Takes a single string argument "directory" which points at the directory
+which contains settings definition files and returns an instance of the
+`SettingsManager` class. In this repository, that directory is
+`naomi/settings/definitions/`. Note that the settings definitions in this
+repository can be found by using the `get_default_settings_directory` function.
+An example of how to initialize this is as follows:
+
+```
+from naomi.settings import get_default_settings_directory, SettingsManager
+
+dir = get_default_settings_directory()
+man = SettingsManager(dir)
+```
+
+### files property
+
+An instance of `SettingsManager` has the "files" property, which returns
+a dictionary of recognized settings definitions in the directory supplied to
+the default constructor. The returned dictionary has keys representing the
+settings definition file, such as "system.settings" or "BBG0.settings". The
+values of the dictionary are fully qualified system paths to the file in
+question.
+
+### from_serial() method
+
+Takes a single bytes argument "serial" as retrieved from Naomi ROM header
+and uses that to construct a `SettingsWrapper` class representing the
+available settings for a game that has the serial number provided. This
+can be used when you want to edit settings for a game but do not have an
+EEPROM already created. This will read the definitions files and create
+a `SettingsWrapper` with default settings. This can be then passed to the
+`to_eeprom()` function to return a valid 128-byte EEPROM representing the
+default settings.
+
+### from_rom() method
+
+Takes a NaomiRom instance argument "rom" and a NaomiRomReginEnum argument
+"region" and retrieves any requested system defaults from the Naomi ROM
+header. It uses that as well as the game's settings definition file to create
+a default EEPROM that is then used to construct a `SettingsWrapper` class
+repressenting the default settings as a Naomi would create them on first
+boot. This can then be edited or passed to the `to_eeprom()` function to
+return a valid 128-byte EEPROM representing the edited settings.
+
+### from_eeprom() method
+
+Takes a single bytes argument "data" as loaded from a valid 128-byte
+EEPROM file or as grabbed from the `data` property of an instance of
+`NaomiEEPRom` and constructs a `SettingsWrapper` class representing the
+available settings for a game that matches the serial number provided in
+the EEPROM file. This can be used when you want to edit the settings for
+a game and you already have the EEPROM file created. This will read the
+definitions file and parse out the current settings in the EEPROM and
+return a `SettingsWrapper` with those settings. This can then be modified
+and passed to the `to_eeprom()` function to return a valid 128-byte EEPROM
+representing the current settings.
+
+### from_json() method
+
+Takes a single dictionary argument "jsondict" and deserializes it to
+a `SettingsWrapper` instance. The dictionary argument can be retrieved
+by calling the `to_json()` method on an existing `SettingsWrapper` instance.
+This is provided specifically as a convenience method for code wishing to
+provide web editor interfaces. A recommended workflow is to create an
+instance of `SettingsManager`, request a `SettingsWrapper` by calling
+either `from_eeprom()` or `from_serial()` as appropriate, calling `to_json()`
+on the resulting `SettingsWrapper` class and then passing that to
+`json.dumps` to get valid JSON that can be sent to a JS frontend app. After
+the frontend app has manipulated the settings by modifying the current
+value of each setting, you can use `json.loads` to get back a dictionary
+that can be passed to this function to get a deserialized `SettingsWrapper`
+class. The deserialized `SettingsWrapper` instance can then be passed to
+the `to_eeprom()` function to return a valid 128-byte EEPROM representing
+the settings chosen by the JS frontend.
+
+### to_eeprom() method
+
+Given an instance of `SettingsWrapper` returned by either `from_serial()`,
+`from_eeprom()` or `from_json()`, calculates and returns a valid 128-byte
+EEPROM file that represents the settings. Use this when you are finished
+modifying system and game settings using code and wish to generate a valid
+EEPROM file that can be modified with `NaomiEEPRom`, placed in an emulator's
+data directory to load those settings or attached to a Naomi ROM using the
+`naomi.NaomiSettingsPatcher` class so that the settings are written when
+netbooting the rom on a Naomi system.
+
+# Settings Definitions Format
+
+Settings definition files are meant to be simple, human readable documentation
+for a game's EEPROM settings. They are written in such a way that on top of
+being human-readable documentation, they can also be parsed by
+`naomi.settings.SettingsManager` to help with making settings editors for any
+game on the Naomi platform. Each setting in a settings definition file represents
+how to parse some number of bytes in a game's EEPROM. You'll notice that while
+there is a size specifier for each setting there is no location specifier. That's
+because each setting is assumed to come directly after the previous setting in
+the section.
+
+All settings sections in an game's EEPROM are assumed to be little-endian, much
+like the Naomi system itself. Defaults and valid values are specified as hex
+digits as copied directly out of a hex editor. When specifying half-byte settings,
+the first setting is assumed to be the top half of the byte (the first hex digit
+that appears when reading the EEPROM in a hex editor) and the second setting is
+assumed to be the bottom half of the byte. All half-byte settings are expected
+to come in pairs.
+
+Aside from the "system.settings" file, all settings files are named after the
+serial number of the game they are associated with. The serial number for the
+game can be found by looking at the ROM header using a tool such as `rominfo`,
+or by looking at bytes 3-7 of an EEPROM that you got out of an emulator and
+loaded into a hex editor.
+
+The only necessary parts of a setting are the name and the size. If the setting
+is user-editable, there should be at least one valid value that the setting is
+allowed to be. Optionally, you can specify the default value for any setting
+and whether the setting is read-only. Additionally, read-only and default values
+can depend on the value of another setting.
+
+Settings are defined by writing any valid string name followed by a colon. Setting
+parts come after the colon and are either comma-separated or are placed one per
+line after the setting name. You can mix and match any number of comma-separated
+parts and parts on their own lines. Whatever makes the most sense and is the most
+readable is allowed. Settings parts can show up in any order after the setting
+name. You can define size, read-only, defaults and valid options in any order you
+wish. The only restriction is that the size part MUST appear before any default parts.
+
+Any line in a settings definition file that starts with a hashtag (`#`) is treated
+as a comment. You can write anything you want in comments so feel free to write
+down any useful information about settings you think somebody else might care to
+know.
+
+## A Simple Setting
+
+The most basic setting is one that has a name, a size and some allowed values.
+An example of such a setting is like so:
+
+```
+Sample Setting: byte, values are 1 to 10
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. Editors that
+display this setting will display a drop-down or selection box that includes
+the decimal values "1", "2", "3", "4", "5", "6", "7", "8", "9", and "10".
+The decimal values for each valid setting is automatically inferred based on
+the range given in the setting.
+
+If you want to specify some alternate text for each valid setting, you may
+do so like so:
+
+```
+Sample Setting: byte, 1 - On, 0 - Off
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01 and 00 applied to it. Editors that display this setting
+will display a drop-down or selection box that includes the value "On" and
+"Off" and will select the correct one based on the value in the EEPROM when it
+is parsed.
+
+You can mix and match how you define settings values if it is most convenient.
+For example, the following setting mixes the two ways of specifying valid
+values:
+
+```
+Sample Setting: byte, 0 - Off, 1 to 9, 10 - MAX
+```
+
+This defines a setting named "Sample Setting" which is a single byte and
+can have the hex values 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. Editors
+that display this setting will display a drop-down or selection box that includes
+the options "Off", "1", "2", "3", "4", "5", "6", "7", "8", "9", "MAX". The
+correct one will be selected based on the value in the EEPROM when it is parsed.
+
+## Changing the Setting Display
+
+Normally, if you have some number of values that a setting can be and you
+want to control what an editor displays when selecting each value, you would
+list each value out individually along with the text it should be displayed as.
+However, if you have a large range of values and you want to display them in
+hex instead of decimal, you can instead do the following:
+
+```
+Sample Setting: byte, values are 1 to 10 in hex
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. This is identical
+to the simple setting in the previous section. However, editors that display this
+setting will display a drop-down or selection box that includes the options
+"01", "02", "03", "04", "05", "06", "07", "08", "09" and "0a". You could have
+written the settings out individually, but for large ranges that you want to
+display in hex this is faster.
+
+## Changing the Setting Size
+
+If your setting spans more than 1 byte, or it is only the top half or bottom
+half of a byte, you can specify that in the size part. For settings that occupy
+more than 1 byte, you can simply write the number of bytes in the part section.
+If a setting only occupies the top or bottom half of a byte, you can specify
+a half-byte for the size.
+
+An example of a setting that takes up 4 bytes is as follows:
+
+```
+Big Setting: 2 bytes, 12 34 - On, 56 78 - Off
+```
+
+This defines a setting named "Big Setting" that takes up two bytes and has
+the two hex values 12 34 and 56 78 as read in a hex editor as its options.
+Editors will display either "On" or "Off" as they would for 1 byte settings.
+
+An example of a pair of settings that take up half a byte each is as follows:
+
+```
+Small Setting 1: half-byte, values are 1 to 2
+Small Setting 2: half-byte, values are 3 to 4
+```
+
+This defines two settings named "Small Setting 1" and "Small Setting 2". Each
+setting takes up half a byte. The first setting, "Small Setting 1", will take
+the top half of the byte, and the second, "Small Setting 2", will take the
+bottom half of the byte. The hex values for each are the same as they would
+be for all other documented settings. Note that the settings came in a pair
+because you have to specify both halves of the byte!
+
+## Specifying Read-Only Settings
+
+Sometimes there is a setting that you can't figure out, or there's a setting
+that the game writes when it initializes the EEPROM but never changes. In this
+case you can mark the setting read-only and editors will not let people see
+or change the setting. However, the setting will still be created when somebody
+needs to make a default EEPROM based on the settings definition file.
+
+An example of how to mark a setting as read-only:
+
+```
+Hidden Setting: byte, read-only
+```
+
+In this case, there is a setting named "Hidden Setting" which is a single
+byte. We specified that it was read-only, so editors will not display the
+setting to the user. Also, since it was read-only, we didn't need to specify
+any allowed values. You can use this when there are parts of the EEPROM you
+don't want people to mess with, or that you don't understand so you just need
+to skip it.
+
+Sometimes there are settings that only display in some scenarios, such as when
+another setting is set to a certain value. If you run into a setting such as
+this, you can specify that relationship like so:
+
+```
+Sometimes Hidden Setting: byte, read-only if Other Setting is 1, values are 0 to 2
+```
+
+This defines a setting called "Sometimes Hidden Setting" which is a single byte
+and can have the hex values 00, 01 and 02. When another setting named "Other
+Setting" is set to 1, this setting becomes read-only and cannot be modified
+by the user. When that other setting named "Other Setting" is set to any other
+value, this setting becomes user-changeable.
+
+If you want to specify that a setting is read-only unless another setting is
+a certain value, you can do so like the following:
+
+```
+Sometimes Hidden Setting: byte, read-only unless Other Setting is 1, values are 0 to 2
+```
+
+This defines the same setting as the first example, but the read-only logic
+is reversed. This setting will be read-only when "Other Setting" is any value
+but 1, and will be user-changeable when "Other Setting" is 1.
+
+If you need to specify multiple values for the other setting, you can do so
+like so:
+
+```
+Sometimes Hidden Setting: byte, read-only if Other Setting is 1 or 2, values are 0 to 2
+```
+
+This defines the same setting as the first example, but the read-only logic
+is changed. The setting will be read only when "Other Setting" is 1 or 2, and
+will be user-changeable when "Other Setting" is any other value.
+
+## Specifying Defaults
+
+Its nice to specify what the default for each setting is. This way, editors
+can make a new EEPROM from scratch for the game you are defining without needing
+an EEPROM to exist first. If you don't specify a default, the default for the
+setting is assumed to be 0. If that isn't a valid value for a setting, you'll
+run into problems so it is best to define defaults for settings when you can.
+
+To specify a default, you can do the following:
+
+```
+Default Setting: byte, default is 1, values are 1, 2
+```
+
+This defines a setting named "Defaut Setting" which is a single byte and whose
+valid values are 01 and 02. The default value when creating an EEPROM from
+scratch is 01.
+
+If a setting is read-only, then when we an EEPROM is edited and saved, the
+default value will take precidence over the current value. If a setting is
+user-editable, then the current value will take precidence over the default
+value. This is so that you can have settings which are optionally read-only
+based on other settings and specify what value the setting should be when
+it is read-only. This isn't often necessary but it can come in handy in some
+specific scenarios.
+
+For example, in Marvel Vs. Capcom 2, the "Continue" setting is defaulted to
+"On". However, if event mode is turned on, then the "Continue" setting is
+forced to "Off" and becomes no longer user-editable. To represent such
+a case as this, you can do something like the following:
+
+```
+Event: byte, default is 0
+ 0 - Off
+ 1 - On
+Continue: byte, read-only if Event is 1, default is 1 if Event is 0, default is 0 if Event is 1
+ 0 - Off
+ 1 - On
+```
+
+This can be a bit daunting to read at first, so let's break it down. First,
+it defines a setting named "Event" which is a byte and can have values 00 and 01.
+Those values are labelled "Off" and "On" respectively. Event mode is off by default.
+Then, it defines a setting named "Continue" which is a byte as well. It has values
+00 and 01 labelled "Off" and "On" respectively. It is user-editable when event mode
+is off, and it is read-only when event mode is on. When event mode is off, the default
+is 01, which corresponds to "On". When event mode is on, the default is "00" which
+corresponds to "Off". Remember how settings that are read-only try to save the
+default first, and settings that are user-changeable try to save the current value
+first? That's where the magic happens. When the "Event" setting is set to "On"
+then the "Continue" setting is read-only, so we will save the default hex value of 00!
+When the "Event" setting is set to "Off", the "Continue" setting is user-changeable so
+we will save whatever value the user selected! When we create a new EEPROM from scratch,
+we set "Event" to 00 which tells the "Continue" setting to default to 01. It all works
+perfectly!
+
+### Specifying Entirely-Dependent Defaults
+
+Sometimes you might run into a setting that seems to be identical to another setting,
+or a setting that seems to be the same as another setting plus or minus some adjustment
+value. If you encounter such a relationship, you can represent it by doing something
+like the following:
+
+```
+Setting: byte, default is 0, values are 1 to 10
+Dependent Setting: byte, read-only, default is value of Setting
+```
+
+This defines a setting named "Setting" which is a single byte that can have hex values
+01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. It defines a second setting named "Dependent
+Setting" which defaults to whatever "Setting" is set to. Since it is read-only, the
+default will take precidence over the current value, so when somebody edits "Setting"
+in an editor, both "Setting" and "Dependent Setting" will be saved with the same value!
+
+In some cases, a setting will be dependent on another setting, but won't have the
+exact same value. If you wanted to, you could list out a whole bunch of default conditionals
+to represent all of the possibilities, like so:
+
+```
+Setting: byte, default is 0, values are 1 to 3
+Dependent Setting: byte, read-only
+ default is 0 if Setting is 1
+ default is 1 if Setting is 2
+ default is 2 if Setting is 3
+```
+
+This would work, and sets up "Dependent Setting" to be 00 when Setting is 01, 01 when
+Setting is 02, and 02 when Setting is 03. However, if there are a lot of possible values
+for "Setting", this can get tedious. Instead, you can represent the relationship like so:
+
+```
+Setting: byte, default is 0, values are 1 to 3
+Dependent Setting: byte, read-only, default is value of Setting - 1
+```
+
+This defines the exact same pair of settings, with the exact same defaults!
+
+## Specifying an Alternate Display Order
+
+Normally settings are displayed in exactly the order the show up in the
+file. Sometimes settings show up in a different order in a game's test
+menu than they appear in the EEPROM file itself. You can't just rearrange
+the order that the settings appear in the definition file since that
+dictates the order that the settings themselves are processed. So, instead
+you can specify that a setting should be displayed before or after another
+setting. Here is an example:
+
+```
+Simple Setting: byte, values are 1 to 10
+Other Setting: byte, values are 2 to 5, display before Simple Setting
+```
+
+This defines two settings named "Simple Setting" and "Other Setting". While
+"Simple Setting" comes first when parsing the EEPROM itself, when it comes
+time to display the settings in an editor, "Other Setting" will be displayed
+first and then "Simple Setting".
+
+Similarly, you can specify that a setting come after another setting like so:
+
+```
+Simple Setting: byte, values are 1 to 10, display after Other Setting
+Other Setting: byte, values are 2 to 5
+```
+
+Both the above examples produce the exact same list of settings in an editor.
+
+## Using ":" or "," in Setting Names or Values
+
+Since these are special characters used to figure out where a setting name ends
+as well as separate sections, using one of these characters in a setting name or
+value description will result in an error. In order to have a setting that
+includes one of these symbols, you can escale it like so:
+
+```
+Setting With A Colon\: The Revengence: byte, 1 - Good\, Very Good, 2 - Bad\, Very Bad
+```
+
+This defines a setting named "Setting With a Colon: The Revengence" that has two
+labelled values consisting of "Good, Very Good" and "Bad, Very Bad". Whenever you
+need to use a character that is special, prefix it with a "\\". This includes the
+"\\" character as it denotes that the next character should be escaped. So if you
+want a "\\" character in your setting name or value, you should use two "\\" characters
+in a row.
+
+
+%package help
+Summary: Development documents and examples for naomiutils
+Provides: python3-naomiutils-doc
+%description help
+# naomi
+
+Collection of routines written in Python for manipulating Naomi ROM and EEPROM
+files. This is geared towards enthusiasts building their own netboot servers or
+RPI setups and provides libraries for examining ROM and manipulating ROM headers
+as well as attaching EEPROM settings to ROM files and manipulating their contents.
+It is fully typed and requires a minimum of Python 3.6 to operate.
+
+## NaomiEEPRom
+
+The NaomiEEPRom class provides high-level accessors to a 128-byte Naomi EEPROM
+dump as obtained through a ROM dumper or from an emulator's saved state. It handles
+correcting various CRCs as well as allowing high-level access to the duplicated
+game and system settings sections. Use this to create or manipulate a raw EEPROM
+data file.
+
+### Default Constructor
+
+Takes a single byte argument "data" and verifies that it is a valid 128-byte EEPROM
+before returning an instance of the `NaomiEEPRom` class used to manipulate that
+data. If any of the CRCs do not match this will raise a `NaomiEEPRomException`.
+
+### NaomiEEPRom.default
+
+An alternate constructor that takes a single byte argument "serial" and an optional
+byte argument "game_defaults" and creates a valid EEPROM based on this data, returning
+an instance of the `NaomiEEPRom` class that can be used to manipulate this newly
+created EEPROM. The serial argument should be exactly bytes and begin with a "B",
+followed by two characters and finally a digit, as represented by a bytestring. This
+is a Naomi system restriction. Optionally, a string of bytes can be given in the
+"game_defaults" section which will be used to determine the length and default
+values of the game section of the EEPROM.
+
+### NaomiEEPRom.validate
+
+A static method that takes a byte argument "data" and checks it for validity. This
+includes making sure the length is 128 bytes and that all CRCs are correct. Optionally
+you can pass in the boolean keyword argument "only_system" set to True to only check
+that the system section is valid. This is useful for validating EEPROMs where the BIOS
+has written system settings but the game has not yet booted and created its own
+defaults yet. You can use this function to ensure that passing data to the default
+constructor will not result in an exception.
+
+### data property
+
+An instance of NaomiEEPRom has the "data" property, which returns a bytes object
+representing the current 128-byte EEPROM. This will have all CRC sections fixed.
+Use the "data" property to retrieve the EEPROM for writing to a file or sending to
+a Naomi system after manipulating data using the NaomiEEPRom class. Note that this
+is read-only, you should not attempt to manipulate the raw data using this property.
+
+## serial property
+
+Returns the 4 byte serial that is found in the system section of the EEPROM. This
+will match a serial given in the `NaomiEEPRom.default` constructor when it is used.
+Use this to help determine what game an EEPROM goes with. Note that this is read-only.
+To modify the serial, create a new EEPROM with that serial. Game settings and system
+settings are not compatible across games on the Naomi platform.
+
+## length property
+
+The length in bytes as an integer of the game section of the EEPROM. If the game section
+is not valid this return 0 bytes. Otherwise it returns the length of the game section
+itself. This property is writeable. If you provide it a new value, the game section
+will be resized to that length. Use this to determine the bounds of the `game` section
+as documented below, as well as to resize the `game` section.
+
+## system property
+
+Returns a bytes-like wrapper object representing the system section of the EEPROM.
+This operates like a bytearray object in Python. That means you can access or mutate
+any byte or section in the system area using this property. Note that this wrapper
+object takes care of reading from and writing to both mirrors of the system section in
+the EEPROM file as well as ensuring that the CRC is correct. Note also that the system
+section is hard-coded to 16 bytes in length which cannot be modified. This is a system
+restriction on the Naomi platform. Much like bytes objects in python, accessing a single
+byte returns an integer in the range of 0-255, but accessing a range returns a bytes
+object.
+
+A simple example of reading bytes 6-8 of the system section:
+
+```
+eeprom = NaomiEEPRom(somedata)
+print(eeprom.system[6:8]) # Will print a bytes object of length 2.
+```
+
+A simple example of writing bytes 10-12 of the system section:
+
+```
+eeprom = NaomiEEPRom(somedata)
+eeprom.system[10:12] = b"\x12\x34"
+```
+
+## game property
+
+Returns a bytes-like wrapper object representing the game section of the EEPROM. This
+operates identically to the `system` property as documented above, only it accesses the
+game section of the EEPROM. Note that for this to work properly, the game section needs
+to be initialized by setting the `length` property on the instance of `NaomiEEPRom`. If
+you are manipulating an existing EEPROM file, this property will already be set for you.
+
+Note that this wrapper object includes a `valid` property which returns if the current
+section is valid in the EEPROM you are manipulating. This will always be `True` for
+the system section. However, if you access the game section on a newly-created EEPROM
+without setting defaults or a length, the game property's `valid` property will return
+`False`.
+
+An example of verifying that the game section is valid:
+
+```
+eeprom = NaomiEEPRom.default(serial=b"BBG0")
+print(eeprom.game.valid) # Will print "False" as the EEPROM was created without a game section default.
+eeprom.length = 20
+print(eeprom.game.valid) # Will print "True" as the EEPROM game section was initialized to be 20 bytes long.
+```
+
+## NaomiRom
+
+The NaomiRom class provides high-level accessors to a Naomi ROM header as found
+at the beginning of a ROM file suitable for netbooting. It handles decoding all
+sections of the ROM header as well as allowing modification and even creation of
+new ROM header sections given valid data. Use this if you wish to manipulate or
+create your own Naomi ROM files form scratch.
+
+### Default Constructor
+
+Takes a single byte argument "data" and uses it as the ROM image where the header
+will be extracted. Note that there is no CRC over the ROM header so any data that
+is 1280 bytes or longer will appear valid.
+
+### NaomiRom.default
+
+An alternate constructor that creates an entirely blank Naomi ROM containing no
+loaded executable or test sections and no ROM name. Use this when you want to
+programatically construct a ROM image, such as when you are building a final ROM
+in a homebrew program you are building for the Naomi platform.
+
+### valid property
+
+An instance of NaomiRom has the "valid" property which will be "True" when the ROM
+passed into the constructor is a valid Naomi ROM and "False" otherwise. This is a
+read-only property as the vailidity of a ROM is entirely dictated by the data
+passed into the constructor.
+
+### data property
+
+The ROM data, as passed into the constructor for the instance of NaomiRom, or as
+created when using `NaomiRom.default` alternate constructor. Note that when any
+of the following properties are written, the `data` property will be changed to
+reflect those settings. Use this to retrieve the updated ROM after you've made
+adjustments to the values you wish to change.
+
+### publisher property
+
+The publisher of this ROM, as a string. When read, grabs the current publisher
+of the ROM image. When written, updates the publisher to the new string provided.
+
+### names property
+
+A dictionary of names indexed by region. Given the current system region, the names
+that show up here will also be the names that show up in the test menu for a given
+game. Note that there are the following constants that can be used to index into the
+names list: `NaomiRomRegionEnum.REGION_JAPAN`, `NaomiRomRegionEnum.REGION_USA`,
+`NaomiRomRegionEnum.REGION_EXPORT`, `NaomiRomRegionEnum.REGION_KOREA`, and finally
+`NaomiRomRegionEnum.REGION_AUSTRALIA`. Note that the last region, Australia, exists
+in many ROM files but is not accessible as there is no Australia BIOS for the Naomi
+platform. When read, grabs a dictionary of names of the ROM given the region. When
+written, updates the ROM names by region using the dictionary provided.
+
+### sequencetexts property
+
+A list of 8 sequence texts that are used by the game for coin insertion messages.
+Many ROMs only have the first sequence set. When read, grabs all 8 sequence texts
+and returns a list of them. When written, updates the sequence texts to the new
+list of strings provided.
+
+### defaults property
+
+A dictionary of NaomiEEPROMDefaults instance representing what defaults the BIOS will
+set in the system EEPROM section when initializing the EEPROM on first boot. Note
+that this is indexed by the same enumeration as the "names" property. When read, grabs
+the defaults and returns them. When written, extracts values from the provided
+NaomiEEPROMDefaults instances and updates the per-region defaults in the ROM accordingly.
+
+### date property
+
+A `datetime.date` instance representing what date the ROM was build and released.
+When read, returns the current date in the ROM header. When written, updates the
+date of the ROM with the new `datetime.date` provided.
+
+### serial property
+
+A 4-byte bytestring representing the serial number of the ROM. This is used to tie
+EEPROM data to the ROM itself and lets the Naomi know when to reset certain defaults.
+When read, returns the current serial from the ROM header. When written, updates the
+serial in the ROM header.
+
+### regions property
+
+A list of NaomiRomRegionEnum values representing valid regions this ROM will run under.
+Uses the same region constants as the `names` property. When read, returns a list of
+the valid regions this ROM executes under. When written, updates the list of regions
+the ROM is allowed to execute under. When booting, the Naomi BIOS will check the
+current region against this list and show an error if the current region is not
+included in the list.
+
+### players property
+
+A list of integers representing the valid number of player configurations that this
+ROM will boot under. Valid player numbers include 1, 2, 3 and 4. When read, returns
+a list of all valid number of player configurations that this game will boot with.
+When written, updates the list of player configurations. When booting, the Naomi
+BIOS will check the "Number of Players" setting in the system assignments and see
+if that setting appears in this list.
+
+### frequencies property
+
+A list of frequencies that the monitor is allowed to run at for this ROM. This
+includes the values 15 and 31. On read, returns the list of allowed frequencies.
+On write, updates the list of allowed frequencies. On boot, the Naomi BIOS will
+check the current horizontal refresh rate of the system as controlled by a DIP
+switch and show an error if it isn't in the list of allowed frequencies.
+
+### orientations property
+
+A list of strings representing the allowed orientations for the monitor for this
+ROM. The includes the values "horizontal" and "vertical". On read, returns the
+list of all acceptable orientations. On write, updates that list based on the
+provided list of strings. On boot, the Naomi BIOS will check the current "Monitor
+Orientation" setting in the system assignments and see if that orientation is
+on this list.
+
+### servicetype property
+
+A string value of either "individual" or "common" for the expected service button
+type for the ROM. On read, returns either "individual" or "common" to represent
+the current service type selected. On write, updates the service type to match
+the string provided.
+
+### main_executable property
+
+An instance of a NaomiExecutable including sections of the ROM that the Naomi
+BIOS will copy before executing the ROM, as well as the entrypoint in main RAM
+that the BIOS will jump to after copying sections. On read, returns the current
+list of sections to copy as well as the main entrypoint, as encapsulated as an
+instance of NaomiExecutable. On write, it updates the ROM to the new executable
+configuration by unpacking the NaomiExecutable instance given.
+
+### test_executable property
+
+This property is identical to the `main_executable` property, except for it
+represents the code and entrypoint that the Naomi BIOS will use when executing
+the "Game Test Mode" section of the test menu. It can be similarly read and written.
+
+## NaomiSettingsPatcher
+
+The NaomiSettingsPatcher class provides logic for attaching an EEPROM or SRAM configuration
+file to a Naomi ROM so that it can be written to the EEPROM/SRAM when netbooting that
+ROM. Note that this is not a supported feature of the Naomi platform, so it uses
+an executable stub that it attaches to the ROM in order to make this work. If you
+do not care what executable stub is attached and only want to patch settings into
+a ROM file, use the `get_default_trojan` function which will return a bytes
+object suitable for passing into a `NaomiSettingsPatcher` constructor.
+
+### Default Constructor
+
+Takes a bytes "rom" argument and a bytes "trojan" argument creates an instance of
+NaomiSettingsPatcher which can attach or retrieve previously-attached EEPROM or SRAM settings
+in a Naomi ROM file suitable for netbooting. An example of how to initialize this
+is as follows:
+
+```
+from naomi import NaomiSettingsPatcher, get_default_trojan
+
+patcher = NaomiSettingsPatcher(somedata, get_default_trojan())
+```
+
+### data property
+
+The same bytes as passed to the `NaomiSettingsPatcher` constructor. After calling
+`put_settings()` as documented below, this will be updated to the new ROM contents
+with the settings applied. A recommended workflow is to patch ROMs on-the-fly when
+netbooting by creating an instance of `NaomiSettingsPatcher` with the ROM data you
+were about to send, calling `put_settings()` with the settings you wish to attach,
+and then getting the data using this property and sending it down the wire to the
+Naomi system. Note that you can attach either an EEPROM file (128 bytes) or an SRAM
+file (32kb) but not both.
+
+### serial property
+
+An instance of NaomiSettingsPatcher has the `serial` property. When read, this
+will examine the serial of the Naomi ROM passed into the constructor and return the
+4 byte serial number, suitable for matching against an EEPROM's system serial. Note
+that this property is read-only.
+
+### rom property
+
+Returns a `NaomiRom` instance that encapsulates the ROM passed into the patcher. This
+instance should not be edited, as it will not be read again when performing the patches.
+Note that this property is read-only.
+
+### has_eeprom property
+
+Returns `True` if the ROM passed into the patcher has an attached EEPROM file. Returns
+`False` otherwise.
+
+### eeprom_info property
+
+Returns an optional instance of NaomiSettingsInfo if the ROM has a configured EEPROM
+section. If the ROM does not have a configured EEPROM section, this returns `None`.
+The NaomiSettingsInfo instance represents the configuration passed to `put_eeprom()`
+on a previous invocation. Note that this property is read-only.
+
+### get_eeprom() method
+
+Returns a 128-byte EEPROM bytestring that was previously attached to the Naomi ROM,
+or `None` if this ROM does not include any EEPROM settings.
+
+### put_eeprom() method
+
+given a bytes "eeprom" argument which is a valid 128-byte EEPROM, ensures that it
+is attached to the Naomi ROM such that the settings are written when netbooting the
+ROM image. If there are already EEPROM settings attached to the ROM, this overwrites
+those with new settings. If there are not already settings attached, this does the
+work necessary to attach the settings file as well as the writing trojan supplied to
+the `NaomiSettingsPatcher` constructor.
+
+Valid EEPROM files can be obtained form a number of places. If you use an emulator
+to set up system and game settings, then the EEPROM file that emulator writes can
+usually be supplied here to make your game boot to the same settings. If you use
+the `NaomiEEPRom` class to manipulate an EEPROM, the data it produces can also be
+supplied here to force the Naomi to use the same settings.
+
+Optionally, pass in the boolean keyword argument "enable_sentinel" set to True and
+the Naomi ROM will re-initialize the settings when netbooting even if the last game
+netbooted was this game. Use this when iterating over settings that you want to choose
+so that you can ensure the settings are written. If you do not provide this argument,
+the default behavior is that settings will not be overwritten when we netboot a game
+that is already running on the system.
+
+Optionally, pass in the boolean keyword argument "enable_debugging" set to True
+which forces the Naomi to display debugging information on the screen before booting
+the game. Use this to see what is actually going on under the hood when using the
+settings patching feature.
+
+Optionally, pass in the boolean keyword argument "verbose" set to True which forces
+the `put_eeprom()` function to output progress text to stdout. Use this if you are
+making a command-line tool and wish to display information about the patch process
+to the user.
+
+### has_sram property
+
+Returns `True` if the ROM passed into the patcher has an attached SRAM file. Returns
+`False` otherwise.
+
+### get_sram() method
+
+Returns a 32k-byte SRAM bytestring that was previously attached to the Naomi ROM, or
+`None` if this ROM does not include any SRAM settings.
+
+### put_sram() method
+
+given a bytes "settings" argument which is a valid 32k-byte SRAM, ensures that it is
+attached to the Naomi ROM such that the settings are written when netbooting the ROM
+image. If there are already SRAM settings attached to the ROM, this overwrites those
+with new settings. If there are not already settings attached, this does the work
+necessary to attach the settings file.
+
+Valid SRAM files can be obtained from an emulator that is capable of writing an SRAM
+file. This only makes sense to use in the context of atomiswave conversions and in
+a select few Naomi games that store their settings in SRAM such as Ikaruga.
+
+Optionally, pass in the boolean keyword argument "verbose" set to True which forces
+the `put_settings()` function to output progress text to stdout. Use this if you are
+making a command-line tool and wish to display information about the patch process
+to the user.
+
+# naomi.settings
+
+Collection of routines written in Python for safe manipulation of 128-byte
+Naomi EEPROM files using supplied system definition files. Essentially, given
+a valid 128-byte EEPROM or a valid 4-byte Naomi ROM serial and a set of system
+and game definition files, `naomi.settings` will provide you a high-level
+representation of valid settings including their defaults, valid values and
+relationships to each other. Settings editors can be built using this module
+which work together with `naomi.NaomiEEPRom` and `naomi.NaomiSettingsPatcher`
+to make the settings available when netbooting a game on a Naomi system.
+
+## Setting
+
+A single setting, with its name, default, current value, possible allowed values,
+and any possible relationship to other settings. Note that any relationship,
+if it exists, will only be to other Setting objects inside a `Settings` class.
+Note that you should not attempt to construct an instance of this yourself.
+You should only work with previously-constructed instances of it as found inside
+an instance of `Settings`.
+
+### name property
+
+The name of this setting, as a string. This is what you should display to a user
+if you are developing a settings editor.
+
+### order property
+
+The order that this setting showed up in the definition file that created it.
+Note that if you are implementing an editor, you can safely ignore this as the
+settings will already be placed in the correct display order.
+
+### size property
+
+The size of this setting, as an instance of SettingSizeEnum. The valid values
+for this are `SettingSizeEnum.NIBBLE` and `SettingSizeEnum.BYTE`. Note that if
+you are developing an editor, you can safely ignore this as the `values` property
+will include all valid values that this setting can be set to. You do not have to
+understand or manipulate this in any way and it is only present so that other
+parts of the `naomi.settings` module can do their job properly.
+
+### length property
+
+The length in bytes this setting takes up, if the `size` property is `SettingSizeEnum.BYTE`.
+If the `size` property is instead `SettingSizeEnum.NIBBLE` then this will always
+be set to 1. Note that much like the `size` property if you are implementing an
+editor you can safely ignore this property for the same rationale as above.
+
+### read_only property
+
+Whether this property is read-only or not. Some settings are not modifiable, such
+as the system serial number. Other settings are only modifiable if other settings
+are set to some value, such as the "Continue" setting on Marvel vs. Capcom 2 which
+is dependent on "Event" mode being off. If this property is "False" then this setting
+is user-editable under all circumstances. If this property is "True" then this setting
+is never user-editable. If this property is an instance of `ReadOnlyCondition` then
+it depends on some other settings for whether it is read-only. You can call the
+`evaluate()` method on the instance of `ReadOnlyCondition` which takes a list of
+`Setting` objects (this setting's siblings as found in a `Settings` object) and returns
+a boolean. If that boolean is "True", then this setting is currently read-only because
+of some other setting's value. If the boolean is "False", then the setting is currently
+editable because of some other setting's value.
+
+In the Naomi Test Mode, settings that are always read-only are hidden completely from
+the user. Settings which are never read-only are displayed to the user. And settings
+which are conditionally read-only will be conditionally hidden based on whether they
+are read-only. It is recommended that your editor perform a similar thing when you
+display settings. Settings whose `read_only` property is "False" should always be
+displayed. Settings whose `read_only` property is "True" should be completely hidden
+from the user. Settings whose `read_only` property is a `ReadOnlyCondition` should be
+evaluated and then the setting either grayed out when it is "True" or conditionally
+hidden from the user.
+
+### values property
+
+A dictionary whose keys are integers which the `current` property could be set
+to, and whose values are the strings which should be displayed to the user for
+those value selections. Note that if a setting is always read-only this may instead
+be None. It is guaranteed to be a dictionary with at least one value whenever a
+setting is user-editable.
+
+### current property
+
+The current integer value that the setting is set to. In order to display the correct
+thing to a user, you should use this as a key into the `values` property to look up
+the correct string to display.
+
+### default property
+
+The default value for this setting. Note that under some circumstances, this may
+not be available and will return None. You can safely ignore this property if you are
+developing an editor. If you wish to provide a "defaults" button in your editor, it
+is recommended to instead use the `from_serial()` or `from_rom()` method on an instance of
+`SettingsManager` which will return you a new `SettingsWrapper` with default values.
+This will correctly handle system and game defaults as well as dependendent default
+settings.
+
+## Settings
+
+A class which represents a collection of settings that can be used to manipulate
+a section of an EEPROM file. Note that you should not attempt to construct
+this yourself. You should only work with previously-constructed instances of
+it as found inside an instance of `SettingsWrapper`.
+
+### filename property
+
+The name of the settings definition file that was used to create this collection.
+Note that this is not a fully qualified path, but instead just the name of
+the file, like "system.settings" or "BBG0.settings". If you wish to look up
+the actual file location given this property, use the `files` property on an
+instance of `SettingsManager`.
+
+### type property
+
+An instance of SettingType which specifies whether this collection of settings
+is a system settings section or a game settings section in an EEPROM. Valid
+values are `SettingType.SYSTEM` and `SettingType.GAME`.
+
+### settings property
+
+A python list of `Setting` objects, representing the list of settings that
+can be mofidied or displayed. You should not assign to this property directly
+when modifying settings in a settings editor you are implementing. However,
+you are welcome to modify the properties of each setting in this list directly.
+
+### length property
+
+An integer representing how many bytes long the section of EEPROM represented
+by this collection is. For system settings, this will always be 16 since the
+system section is hardcoded at 16 bytes. For game settings, this will be
+determined by the settings definition file that was looked up for the game
+in question.
+
+## SettingsWrapper
+
+A class whose sole purpose is to encapsulate a group of system settings,
+game settings and the serial number of the game that the system and game
+settings go with. This is returned by many methods in `SettingsManager`
+and taken as a parameter of several more methods in `SettingsManager.
+
+Note that you should not attempt to construct this yourself. You should
+only work with previously-constructed instances of it as returned by
+methods in `SettingsManager`.
+
+### serial property
+
+The 4-byte serial of the game this `SettingsWrapper` instance has been
+created for.
+
+### system
+
+A collection of settings that manipulate the system section of the EEPROM
+for the game this instance has been created for. This is inside of a
+`Settings` wrapper object.
+
+### game
+
+A collection of settings that manipulate the game section of the EEPROM
+for the game this instance has been created for. This is inside of a
+`Settings` wrapper object.
+
+### to_json() method
+
+Converts the current instance of `SettingsWrapper` to a dictionary suitable
+for passing to `json.dumps`. This is provided as a convenience wrapper so
+that if you are implementing a web interface you don't have to serialize
+anything yourself. To unserialize a dictionary that you get from this method,
+call the `from_json` method on an instance of `SettingsManager`.
+
+## SettingsManager
+
+The `SettingsManager` class manages the ability to parse a 128-byte EEPROM
+file given a directory of settings definitions. It is responsible for
+identifying the correct files for patching given an EEPROM or ROM serial.
+It is also responsible for taking a modified list of settings and writing
+a new EEPROM file.
+
+Note that default definitions are included with this module. To grab the
+default definitions directory, use the `get_default_settings_directory` function
+which will return a fully qualified path to the settings directory of this
+module.
+
+Note that since this is parsing user-supplied settings definitions files,
+there can be errors in processing those files. In any function that returns
+a `SettingsWrapper` instance, a `SettingsParseException` can be thrown.
+This is a subclass of `Exception` so you can get the error message to
+display to a user by calling `str()` on the exception instance. The instance
+will also have a `filename` property which is the filename of the settings
+definition file that caused the problem.
+
+There can also be problems in saving EEPROM settings given the same definitions
+files. In this case, a `SettingsSaveException` can be thrown. This is identical
+to `SettingsParseException` save for the source, so all of the above documentation
+applies.
+
+There can also be problems in deserializing JSON data when calling the
+`from_json()` method. In this case, a `JSONParseException` can be thrown. Similar
+to the above two exceptions, calling `str()` on the instance will give you back
+an error message that can be displayed to a user. The instance will also have
+a `context` property which is the exact location in the JSON where the failure
+occured as represented by a list of attributes that were dereferenced in the
+JSON to get to the section that had an error.
+
+### Default Constructor
+
+Takes a single string argument "directory" which points at the directory
+which contains settings definition files and returns an instance of the
+`SettingsManager` class. In this repository, that directory is
+`naomi/settings/definitions/`. Note that the settings definitions in this
+repository can be found by using the `get_default_settings_directory` function.
+An example of how to initialize this is as follows:
+
+```
+from naomi.settings import get_default_settings_directory, SettingsManager
+
+dir = get_default_settings_directory()
+man = SettingsManager(dir)
+```
+
+### files property
+
+An instance of `SettingsManager` has the "files" property, which returns
+a dictionary of recognized settings definitions in the directory supplied to
+the default constructor. The returned dictionary has keys representing the
+settings definition file, such as "system.settings" or "BBG0.settings". The
+values of the dictionary are fully qualified system paths to the file in
+question.
+
+### from_serial() method
+
+Takes a single bytes argument "serial" as retrieved from Naomi ROM header
+and uses that to construct a `SettingsWrapper` class representing the
+available settings for a game that has the serial number provided. This
+can be used when you want to edit settings for a game but do not have an
+EEPROM already created. This will read the definitions files and create
+a `SettingsWrapper` with default settings. This can be then passed to the
+`to_eeprom()` function to return a valid 128-byte EEPROM representing the
+default settings.
+
+### from_rom() method
+
+Takes a NaomiRom instance argument "rom" and a NaomiRomReginEnum argument
+"region" and retrieves any requested system defaults from the Naomi ROM
+header. It uses that as well as the game's settings definition file to create
+a default EEPROM that is then used to construct a `SettingsWrapper` class
+repressenting the default settings as a Naomi would create them on first
+boot. This can then be edited or passed to the `to_eeprom()` function to
+return a valid 128-byte EEPROM representing the edited settings.
+
+### from_eeprom() method
+
+Takes a single bytes argument "data" as loaded from a valid 128-byte
+EEPROM file or as grabbed from the `data` property of an instance of
+`NaomiEEPRom` and constructs a `SettingsWrapper` class representing the
+available settings for a game that matches the serial number provided in
+the EEPROM file. This can be used when you want to edit the settings for
+a game and you already have the EEPROM file created. This will read the
+definitions file and parse out the current settings in the EEPROM and
+return a `SettingsWrapper` with those settings. This can then be modified
+and passed to the `to_eeprom()` function to return a valid 128-byte EEPROM
+representing the current settings.
+
+### from_json() method
+
+Takes a single dictionary argument "jsondict" and deserializes it to
+a `SettingsWrapper` instance. The dictionary argument can be retrieved
+by calling the `to_json()` method on an existing `SettingsWrapper` instance.
+This is provided specifically as a convenience method for code wishing to
+provide web editor interfaces. A recommended workflow is to create an
+instance of `SettingsManager`, request a `SettingsWrapper` by calling
+either `from_eeprom()` or `from_serial()` as appropriate, calling `to_json()`
+on the resulting `SettingsWrapper` class and then passing that to
+`json.dumps` to get valid JSON that can be sent to a JS frontend app. After
+the frontend app has manipulated the settings by modifying the current
+value of each setting, you can use `json.loads` to get back a dictionary
+that can be passed to this function to get a deserialized `SettingsWrapper`
+class. The deserialized `SettingsWrapper` instance can then be passed to
+the `to_eeprom()` function to return a valid 128-byte EEPROM representing
+the settings chosen by the JS frontend.
+
+### to_eeprom() method
+
+Given an instance of `SettingsWrapper` returned by either `from_serial()`,
+`from_eeprom()` or `from_json()`, calculates and returns a valid 128-byte
+EEPROM file that represents the settings. Use this when you are finished
+modifying system and game settings using code and wish to generate a valid
+EEPROM file that can be modified with `NaomiEEPRom`, placed in an emulator's
+data directory to load those settings or attached to a Naomi ROM using the
+`naomi.NaomiSettingsPatcher` class so that the settings are written when
+netbooting the rom on a Naomi system.
+
+# Settings Definitions Format
+
+Settings definition files are meant to be simple, human readable documentation
+for a game's EEPROM settings. They are written in such a way that on top of
+being human-readable documentation, they can also be parsed by
+`naomi.settings.SettingsManager` to help with making settings editors for any
+game on the Naomi platform. Each setting in a settings definition file represents
+how to parse some number of bytes in a game's EEPROM. You'll notice that while
+there is a size specifier for each setting there is no location specifier. That's
+because each setting is assumed to come directly after the previous setting in
+the section.
+
+All settings sections in an game's EEPROM are assumed to be little-endian, much
+like the Naomi system itself. Defaults and valid values are specified as hex
+digits as copied directly out of a hex editor. When specifying half-byte settings,
+the first setting is assumed to be the top half of the byte (the first hex digit
+that appears when reading the EEPROM in a hex editor) and the second setting is
+assumed to be the bottom half of the byte. All half-byte settings are expected
+to come in pairs.
+
+Aside from the "system.settings" file, all settings files are named after the
+serial number of the game they are associated with. The serial number for the
+game can be found by looking at the ROM header using a tool such as `rominfo`,
+or by looking at bytes 3-7 of an EEPROM that you got out of an emulator and
+loaded into a hex editor.
+
+The only necessary parts of a setting are the name and the size. If the setting
+is user-editable, there should be at least one valid value that the setting is
+allowed to be. Optionally, you can specify the default value for any setting
+and whether the setting is read-only. Additionally, read-only and default values
+can depend on the value of another setting.
+
+Settings are defined by writing any valid string name followed by a colon. Setting
+parts come after the colon and are either comma-separated or are placed one per
+line after the setting name. You can mix and match any number of comma-separated
+parts and parts on their own lines. Whatever makes the most sense and is the most
+readable is allowed. Settings parts can show up in any order after the setting
+name. You can define size, read-only, defaults and valid options in any order you
+wish. The only restriction is that the size part MUST appear before any default parts.
+
+Any line in a settings definition file that starts with a hashtag (`#`) is treated
+as a comment. You can write anything you want in comments so feel free to write
+down any useful information about settings you think somebody else might care to
+know.
+
+## A Simple Setting
+
+The most basic setting is one that has a name, a size and some allowed values.
+An example of such a setting is like so:
+
+```
+Sample Setting: byte, values are 1 to 10
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. Editors that
+display this setting will display a drop-down or selection box that includes
+the decimal values "1", "2", "3", "4", "5", "6", "7", "8", "9", and "10".
+The decimal values for each valid setting is automatically inferred based on
+the range given in the setting.
+
+If you want to specify some alternate text for each valid setting, you may
+do so like so:
+
+```
+Sample Setting: byte, 1 - On, 0 - Off
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01 and 00 applied to it. Editors that display this setting
+will display a drop-down or selection box that includes the value "On" and
+"Off" and will select the correct one based on the value in the EEPROM when it
+is parsed.
+
+You can mix and match how you define settings values if it is most convenient.
+For example, the following setting mixes the two ways of specifying valid
+values:
+
+```
+Sample Setting: byte, 0 - Off, 1 to 9, 10 - MAX
+```
+
+This defines a setting named "Sample Setting" which is a single byte and
+can have the hex values 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. Editors
+that display this setting will display a drop-down or selection box that includes
+the options "Off", "1", "2", "3", "4", "5", "6", "7", "8", "9", "MAX". The
+correct one will be selected based on the value in the EEPROM when it is parsed.
+
+## Changing the Setting Display
+
+Normally, if you have some number of values that a setting can be and you
+want to control what an editor displays when selecting each value, you would
+list each value out individually along with the text it should be displayed as.
+However, if you have a large range of values and you want to display them in
+hex instead of decimal, you can instead do the following:
+
+```
+Sample Setting: byte, values are 1 to 10 in hex
+```
+
+This defines a setting named "Sample Setting" which is a single byte and can
+have the hex values 01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. This is identical
+to the simple setting in the previous section. However, editors that display this
+setting will display a drop-down or selection box that includes the options
+"01", "02", "03", "04", "05", "06", "07", "08", "09" and "0a". You could have
+written the settings out individually, but for large ranges that you want to
+display in hex this is faster.
+
+## Changing the Setting Size
+
+If your setting spans more than 1 byte, or it is only the top half or bottom
+half of a byte, you can specify that in the size part. For settings that occupy
+more than 1 byte, you can simply write the number of bytes in the part section.
+If a setting only occupies the top or bottom half of a byte, you can specify
+a half-byte for the size.
+
+An example of a setting that takes up 4 bytes is as follows:
+
+```
+Big Setting: 2 bytes, 12 34 - On, 56 78 - Off
+```
+
+This defines a setting named "Big Setting" that takes up two bytes and has
+the two hex values 12 34 and 56 78 as read in a hex editor as its options.
+Editors will display either "On" or "Off" as they would for 1 byte settings.
+
+An example of a pair of settings that take up half a byte each is as follows:
+
+```
+Small Setting 1: half-byte, values are 1 to 2
+Small Setting 2: half-byte, values are 3 to 4
+```
+
+This defines two settings named "Small Setting 1" and "Small Setting 2". Each
+setting takes up half a byte. The first setting, "Small Setting 1", will take
+the top half of the byte, and the second, "Small Setting 2", will take the
+bottom half of the byte. The hex values for each are the same as they would
+be for all other documented settings. Note that the settings came in a pair
+because you have to specify both halves of the byte!
+
+## Specifying Read-Only Settings
+
+Sometimes there is a setting that you can't figure out, or there's a setting
+that the game writes when it initializes the EEPROM but never changes. In this
+case you can mark the setting read-only and editors will not let people see
+or change the setting. However, the setting will still be created when somebody
+needs to make a default EEPROM based on the settings definition file.
+
+An example of how to mark a setting as read-only:
+
+```
+Hidden Setting: byte, read-only
+```
+
+In this case, there is a setting named "Hidden Setting" which is a single
+byte. We specified that it was read-only, so editors will not display the
+setting to the user. Also, since it was read-only, we didn't need to specify
+any allowed values. You can use this when there are parts of the EEPROM you
+don't want people to mess with, or that you don't understand so you just need
+to skip it.
+
+Sometimes there are settings that only display in some scenarios, such as when
+another setting is set to a certain value. If you run into a setting such as
+this, you can specify that relationship like so:
+
+```
+Sometimes Hidden Setting: byte, read-only if Other Setting is 1, values are 0 to 2
+```
+
+This defines a setting called "Sometimes Hidden Setting" which is a single byte
+and can have the hex values 00, 01 and 02. When another setting named "Other
+Setting" is set to 1, this setting becomes read-only and cannot be modified
+by the user. When that other setting named "Other Setting" is set to any other
+value, this setting becomes user-changeable.
+
+If you want to specify that a setting is read-only unless another setting is
+a certain value, you can do so like the following:
+
+```
+Sometimes Hidden Setting: byte, read-only unless Other Setting is 1, values are 0 to 2
+```
+
+This defines the same setting as the first example, but the read-only logic
+is reversed. This setting will be read-only when "Other Setting" is any value
+but 1, and will be user-changeable when "Other Setting" is 1.
+
+If you need to specify multiple values for the other setting, you can do so
+like so:
+
+```
+Sometimes Hidden Setting: byte, read-only if Other Setting is 1 or 2, values are 0 to 2
+```
+
+This defines the same setting as the first example, but the read-only logic
+is changed. The setting will be read only when "Other Setting" is 1 or 2, and
+will be user-changeable when "Other Setting" is any other value.
+
+## Specifying Defaults
+
+Its nice to specify what the default for each setting is. This way, editors
+can make a new EEPROM from scratch for the game you are defining without needing
+an EEPROM to exist first. If you don't specify a default, the default for the
+setting is assumed to be 0. If that isn't a valid value for a setting, you'll
+run into problems so it is best to define defaults for settings when you can.
+
+To specify a default, you can do the following:
+
+```
+Default Setting: byte, default is 1, values are 1, 2
+```
+
+This defines a setting named "Defaut Setting" which is a single byte and whose
+valid values are 01 and 02. The default value when creating an EEPROM from
+scratch is 01.
+
+If a setting is read-only, then when we an EEPROM is edited and saved, the
+default value will take precidence over the current value. If a setting is
+user-editable, then the current value will take precidence over the default
+value. This is so that you can have settings which are optionally read-only
+based on other settings and specify what value the setting should be when
+it is read-only. This isn't often necessary but it can come in handy in some
+specific scenarios.
+
+For example, in Marvel Vs. Capcom 2, the "Continue" setting is defaulted to
+"On". However, if event mode is turned on, then the "Continue" setting is
+forced to "Off" and becomes no longer user-editable. To represent such
+a case as this, you can do something like the following:
+
+```
+Event: byte, default is 0
+ 0 - Off
+ 1 - On
+Continue: byte, read-only if Event is 1, default is 1 if Event is 0, default is 0 if Event is 1
+ 0 - Off
+ 1 - On
+```
+
+This can be a bit daunting to read at first, so let's break it down. First,
+it defines a setting named "Event" which is a byte and can have values 00 and 01.
+Those values are labelled "Off" and "On" respectively. Event mode is off by default.
+Then, it defines a setting named "Continue" which is a byte as well. It has values
+00 and 01 labelled "Off" and "On" respectively. It is user-editable when event mode
+is off, and it is read-only when event mode is on. When event mode is off, the default
+is 01, which corresponds to "On". When event mode is on, the default is "00" which
+corresponds to "Off". Remember how settings that are read-only try to save the
+default first, and settings that are user-changeable try to save the current value
+first? That's where the magic happens. When the "Event" setting is set to "On"
+then the "Continue" setting is read-only, so we will save the default hex value of 00!
+When the "Event" setting is set to "Off", the "Continue" setting is user-changeable so
+we will save whatever value the user selected! When we create a new EEPROM from scratch,
+we set "Event" to 00 which tells the "Continue" setting to default to 01. It all works
+perfectly!
+
+### Specifying Entirely-Dependent Defaults
+
+Sometimes you might run into a setting that seems to be identical to another setting,
+or a setting that seems to be the same as another setting plus or minus some adjustment
+value. If you encounter such a relationship, you can represent it by doing something
+like the following:
+
+```
+Setting: byte, default is 0, values are 1 to 10
+Dependent Setting: byte, read-only, default is value of Setting
+```
+
+This defines a setting named "Setting" which is a single byte that can have hex values
+01, 02, 03, 04, 05, 06, 07, 08, 09 and 0a. It defines a second setting named "Dependent
+Setting" which defaults to whatever "Setting" is set to. Since it is read-only, the
+default will take precidence over the current value, so when somebody edits "Setting"
+in an editor, both "Setting" and "Dependent Setting" will be saved with the same value!
+
+In some cases, a setting will be dependent on another setting, but won't have the
+exact same value. If you wanted to, you could list out a whole bunch of default conditionals
+to represent all of the possibilities, like so:
+
+```
+Setting: byte, default is 0, values are 1 to 3
+Dependent Setting: byte, read-only
+ default is 0 if Setting is 1
+ default is 1 if Setting is 2
+ default is 2 if Setting is 3
+```
+
+This would work, and sets up "Dependent Setting" to be 00 when Setting is 01, 01 when
+Setting is 02, and 02 when Setting is 03. However, if there are a lot of possible values
+for "Setting", this can get tedious. Instead, you can represent the relationship like so:
+
+```
+Setting: byte, default is 0, values are 1 to 3
+Dependent Setting: byte, read-only, default is value of Setting - 1
+```
+
+This defines the exact same pair of settings, with the exact same defaults!
+
+## Specifying an Alternate Display Order
+
+Normally settings are displayed in exactly the order the show up in the
+file. Sometimes settings show up in a different order in a game's test
+menu than they appear in the EEPROM file itself. You can't just rearrange
+the order that the settings appear in the definition file since that
+dictates the order that the settings themselves are processed. So, instead
+you can specify that a setting should be displayed before or after another
+setting. Here is an example:
+
+```
+Simple Setting: byte, values are 1 to 10
+Other Setting: byte, values are 2 to 5, display before Simple Setting
+```
+
+This defines two settings named "Simple Setting" and "Other Setting". While
+"Simple Setting" comes first when parsing the EEPROM itself, when it comes
+time to display the settings in an editor, "Other Setting" will be displayed
+first and then "Simple Setting".
+
+Similarly, you can specify that a setting come after another setting like so:
+
+```
+Simple Setting: byte, values are 1 to 10, display after Other Setting
+Other Setting: byte, values are 2 to 5
+```
+
+Both the above examples produce the exact same list of settings in an editor.
+
+## Using ":" or "," in Setting Names or Values
+
+Since these are special characters used to figure out where a setting name ends
+as well as separate sections, using one of these characters in a setting name or
+value description will result in an error. In order to have a setting that
+includes one of these symbols, you can escale it like so:
+
+```
+Setting With A Colon\: The Revengence: byte, 1 - Good\, Very Good, 2 - Bad\, Very Bad
+```
+
+This defines a setting named "Setting With a Colon: The Revengence" that has two
+labelled values consisting of "Good, Very Good" and "Bad, Very Bad". Whenever you
+need to use a character that is special, prefix it with a "\\". This includes the
+"\\" character as it denotes that the next character should be escaped. So if you
+want a "\\" character in your setting name or value, you should use two "\\" characters
+in a row.
+
+
+%prep
+%autosetup -n naomiutils-0.5.4
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-naomiutils -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Mon May 29 2023 Python_Bot <Python_Bot@openeuler.org> - 0.5.4-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..19e23f1
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+5099ce17fd505aea5ad09a55db7f720b naomiutils-0.5.4.tar.gz