diff options
| author | CoprDistGit <infra@openeuler.org> | 2023-05-29 11:09:46 +0000 |
|---|---|---|
| committer | CoprDistGit <infra@openeuler.org> | 2023-05-29 11:09:46 +0000 |
| commit | 43c783cd4049db938cd8dae541959f11b2767ff1 (patch) | |
| tree | 78f3c8ebb63cdd514bbde9bfdc304a4d3ee40c3f | |
| parent | ff4c65e5e2d39a7930c4415534f886e55037e8cc (diff) | |
automatic import of python-naomiutils
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | python-naomiutils.spec | 3095 | ||||
| -rw-r--r-- | sources | 1 |
3 files changed, 3097 insertions, 0 deletions
@@ -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 @@ -0,0 +1 @@ +5099ce17fd505aea5ad09a55db7f720b naomiutils-0.5.4.tar.gz |
