|
pico9918-core 1.3.0
TMS9918A / F18A video display processor emulation in C99
|
pico9918-core - Config semantics More...
Include dependency graph for pico9918_config.c:Go to the source code of this file.
Macros | |
| #define | CONFIG_APPLIED_CB tms9918->configApplied |
Functions | |
| void | pico9918_config_refresh_pending_mirror (uint8_t config[CONFIG_BYTES], uint8_t state) |
| copy live tracked fields into the in-RAM pending mirror with the given state | |
| void | pico9918_config_pending_capture (const uint8_t config[CONFIG_BYTES], uint8_t *record) |
| copy the live tracked fields into a PICO9918_PENDING_RECORD_BYTES record | |
| void | pico9918_config_pending_restore (uint8_t config[CONFIG_BYTES], const uint8_t *record) |
| copy a pending record's field slots back over the live config | |
| PICO9918_INLINE_HOT uint16_t | configStoredVersion (const uint8_t *config) |
| static bool | configOutOfRange (const uint8_t *config) |
| void | pico9918_config_defaults (uint8_t config[CONFIG_BYTES]) |
| write a complete, valid settings block: every field at its default | |
| static void | migrateNewFields (uint8_t *config, uint16_t storedVer) |
| bool | pico9918_config_validate (uint8_t config[CONFIG_BYTES], pico9918_config_host_id_t id) |
validate a config block just read from host storage, and stamp id into it | |
| void | pico9918_config_prepare_save (uint8_t config[CONFIG_BYTES], pico9918_config_host_id_t id) |
stamp id and the initialised marker into a block about to be persisted | |
| uint8_t * | pico9918_config (pico9918_t *tms9918) |
| the instance's CONFIG_BYTES settings block | |
| void | pico9918_config_set_applied_callback (pico9918_t *tms9918, pico9918_config_applied_fn cb, void *userdata) |
| register the host's config-applied hook | |
| static void | configAppliedFire (pico9918_t *tms9918) |
| void | pico9918_config_apply (pico9918_t *tms9918) |
| apply the config block's VDP-side effects: registers 50 and 30, the palette unpack, and the derived PICO9918_CONF_DIAG summary byte | |
| void | pico9918_config_schedule_apply (pico9918_t *tms9918, bool applyVdpEffects) |
| ask for the block to be applied at the next end of frame | |
| void | pico9918_config_apply_now (pico9918_t *tms9918, bool applyVdpEffects) |
| apply the block now, and cancel any apply already owed | |
Variables | |
| const pico9918_config_field_t | pico9918_config_fields [] |
| const size_t | pico9918_config_field_count = sizeof(pico9918_config_fields) / sizeof(pico9918_config_fields[0]) |
pico9918-core - Config semantics
Copyright (c) 2021 Troy Schrapel
This code is licensed under the MIT license
https://github.com/visrealm/pico9918-core
Portable half of the config block: the field descriptor table, the validation / defaults / migration driver, the pending mirror refresh, and the VDP-side apply. Host storage (flash), host detection (SCART, hardware version) and host-side apply effects (VGA scanlines) live in the host.
Definition in file pico9918_config.c.
| #define CONFIG_APPLIED_CB tms9918->configApplied |
Definition at line 181 of file pico9918_config.c.
| void pico9918_config_refresh_pending_mirror | ( | uint8_t | config[CONFIG_BYTES], |
| uint8_t | state | ||
| ) |
copy live tracked fields into the in-RAM pending mirror with the given state
Definition at line 41 of file pico9918_config.c.
References pico9918_config_field_t::offset, PENDING_MIRROR_NONE, and pico9918_config_field_t::pendingMirror.
| void pico9918_config_pending_capture | ( | const uint8_t | config[CONFIG_BYTES], |
| uint8_t * | record | ||
| ) |
copy the live tracked fields into a PICO9918_PENDING_RECORD_BYTES record
Definition at line 51 of file pico9918_config.c.
References pico9918_config_field_t::offset, PENDING_MIRROR_NONE, and pico9918_config_field_t::pendingMirror.
| void pico9918_config_pending_restore | ( | uint8_t | config[CONFIG_BYTES], |
| const uint8_t * | record | ||
| ) |
copy a pending record's field slots back over the live config
Definition at line 61 of file pico9918_config.c.
References pico9918_config_field_t::offset, PENDING_MIRROR_NONE, and pico9918_config_field_t::pendingMirror.
| PICO9918_INLINE_HOT uint16_t configStoredVersion | ( | const uint8_t * | config | ) |
Definition at line 71 of file pico9918_config.c.
|
static |
Definition at line 76 of file pico9918_config.c.
| void pico9918_config_defaults | ( | uint8_t | config[CONFIG_BYTES] | ) |
write a complete, valid settings block: every field at its default
What a host wants when it has nothing stored, and the reason it should not simply zero the block: the field defaults happen to be zero today, but the palette's are not, and pico9918_config_apply() unpacks those bytes into the live palette. A zeroed block therefore renders black. This also sets the initialised marker that pico9918_config_validate() looks for, so a block from here survives it untouched.
The identity bytes at 0-3 are cleared with the rest; pico9918_config_validate() and pico9918_config_prepare_save() are where a host's own identity is stamped in.
Definition at line 85 of file pico9918_config.c.
References CONFIG_BYTES, pico9918_config_field_t::defaultValue, pico9918_config_field_t::offset, and pico9918_default_palette().
Referenced by pico9918_config_validate().
|
static |
Definition at line 105 of file pico9918_config.c.
| bool pico9918_config_validate | ( | uint8_t | config[CONFIG_BYTES], |
| pico9918_config_host_id_t | id | ||
| ) |
validate a config block just read from host storage, and stamp id into it
Resets the block to defaults if it is not this host's, is uninitialised, or holds an out-of-range field; then defaults the fields introduced since the stored version. Either way the identity bytes end up at id and the command bytes a host persisted are cleared.
Returns true if the block changed in a way the host should persist. A host running the configurator protocol can ignore that: PICO9918_CONF_SAVE_FORCED is set on the same path, which is the save request its GPU loop already dispatches.
Definition at line 116 of file pico9918_config.c.
References pico9918_config_defaults().
| void pico9918_config_prepare_save | ( | uint8_t | config[CONFIG_BYTES], |
| pico9918_config_host_id_t | id | ||
| ) |
stamp id and the initialised marker into a block about to be persisted
The marker is how pico9918_config_validate() tells a stored block from an erased one, so a host that persists a block without this gets a factory reset on its next boot. Host storage is untouched - this only prepares the bytes.
Definition at line 150 of file pico9918_config.c.
| uint8_t * pico9918_config | ( | pico9918_t * | tms9918 | ) |
the instance's CONFIG_BYTES settings block
The same bytes pico9918_config_validate() checks and pico9918_config_apply() acts on, so a host reads its stored block into this and applies it. Persistence stays the host's - the library never reaches storage - and so does the decision to write, since these are settings a user chose rather than VDP state.
Definition at line 166 of file pico9918_config.c.
| void pico9918_config_set_applied_callback | ( | pico9918_t * | tms9918, |
| pico9918_config_applied_fn | cb, | ||
| void * | userdata | ||
| ) |
register the host's config-applied hook
Fires from pico9918_config_apply(), which the frame module calls where the configDirty flag is actually consumed - the end-of-frame interrupt, not the scanline body - so it is per-frame at worst and a function pointer is permitted. It exists so a host's own apply effects stay in lockstep with the library's register and palette effects, instead of the host having to watch configDirty itself.
Called LAST, after the VDP-side effects, and on every personality: a host effect is the host's to gate, and one derived from a register has to read the value this call may just have seeded. NULL (the default) means the host has no such effects and nothing is called.
Registered per instance in a multi-instance build - see pico9918.h for why the two builds take different shapes.
Definition at line 184 of file pico9918_config.c.
|
inlinestatic |
Definition at line 192 of file pico9918_config.c.
| void pico9918_config_apply | ( | pico9918_t * | tms9918 | ) |
apply the config block's VDP-side effects: registers 50 and 30, the palette unpack, and the derived PICO9918_CONF_DIAG summary byte
A settings block is a PICO9918 thing, so the effects land only on a personality that has the config port. On an F18A those registers and that palette are the guest's alone, and a block read from host storage must not touch them.
What it writes is a power-on default, not an owner: it runs when the block is loaded and after a reset has cleared the register file, and a later write to register 50 or 30 stands on every personality.
Host-side effects stay with the host.
Definition at line 197 of file pico9918_config.c.
References PICO9918_BASE_TMS9918, PICO9918_BASE_V9938, PICO9918_INST_ONLY, PICO9918_R50_VSCANLINES, PICO9918_REG_ENHANCED2, and PICO9918_REG_MAX_SCAN_SPRITES.
Referenced by pico9918_config_apply_now(), and pico9918_frame_raise_end_of_frame_int().
| void pico9918_config_schedule_apply | ( | pico9918_t * | tms9918, |
| bool | applyVdpEffects | ||
| ) |
ask for the block to be applied at the next end of frame
The deferred form, and what a device wants: the apply seeds registers and republishes the palette, so doing it mid-frame would show on the line being scanned out. applyVdpEffects asks for that reseeding; without it the apply runs its host-side and derived effects only.
A host that has no frame boundary to wait for wants pico9918_config_apply_now().
Definition at line 243 of file pico9918_config.c.
| void pico9918_config_apply_now | ( | pico9918_t * | tms9918, |
| bool | applyVdpEffects | ||
| ) |
apply the block now, and cancel any apply already owed
For a host that has just written the block itself - a configurator front end, or a consumer stepping the library a frame at a time - and would rather see the effects than wait for a boundary it does not have. The deferred request is cleared, so the next end of frame does not apply the same block a second time.
Definition at line 249 of file pico9918_config.c.
References pico9918_config_apply(), and PICO9918_INST_ONLY.
| const pico9918_config_field_t pico9918_config_fields[] |
Definition at line 21 of file pico9918_config.c.
| const size_t pico9918_config_field_count = sizeof(pico9918_config_fields) / sizeof(pico9918_config_fields[0]) |
Definition at line 39 of file pico9918_config.c.