Skip to content

feat(recipes): save and apply looks as recipes, and set GRKit for U1 to U3 - #86

Open
ahonn wants to merge 26 commits into
mainfrom
feat/recipes
Open

ahonn wants to merge 26 commits into
mainfrom
feat/recipes

Conversation

@ahonn

@ahonn ahonn commented Nov 10, 2026

Copy link
Copy Markdown
Owner

Change

Recipes save a whole look on the camera: Film Look or Image Control, grain, glow, white balance, the corrections, and the exposure settings. Apply a recipe, undo it, or save the current settings in ADJ. In MENU, list, apply, rename, and delete recipes. The site lists the recipes of the card and offers popular recipes.

U1, U2, and U3 of the mode dial can apply a recipe, apply GRKit settings saved in that user mode, or turn GRKit off. Enable at Start chooses whether GRKit is on at each start.

ahonn and others added 26 commits November 10, 2026 16:49
Co-authored-by: iceboerg00 <mike.graumann00@gmail.com>
Add the RECIPES module and the core capability CORE.RECIPE. The camera
keeps one list of up to 64 recipes in GRKIT/RECIPES.TXT, which the loader
saves apart from the state file. At most 40 recipes are on, as with the
film looks: they come first, and ADJ and MENU list only them. The camera
keeps the recipes that are off for the site. The page in ADJ lists Undo
while an undo step exists, the recipes that ADJ shows, and Save Settings.
OK on a recipe applies it and closes ADJ, and the camera keeps the last 5
undo steps until power-off.

- A recipe holds the Film Look effect with its Fn adjustments, or the
  native Image Control type with its parameters and native grain. It
  also holds the Grain level and size, the Bloom, Halation, and Halation
  color of Glow, the white balance with its shifts, the correction and
  noise reduction settings, and the exposure settings: the compensation,
  the Auto ISO upper limit, metering, and the ND filter.
- Apply writes the native settings through UserData Set. It sets only
  the capabilities and module settings that loaded modules have, and
  says so when it leaves out a Grain or a Glow. It rounds the
  compensation and the ISO limit to the steps of the camera.
- A recipe saved on the camera holds no exposure settings, and the
  exposure settings do not decide which recipe is the current one.
- An effect recipe finds its effect by the hash of the effect ID. A
  recipe whose effect is not installed has a mark after its name, and
  REPORT.TXT names each recipe that does not apply in full.
- A package can carry a library in SCRIPT/GRKIT/RECIPES.BIN. INSTALL adds
  each recipe of the camera's own line that the list does not hold, with
  its on or off, once for each library, so a deleted recipe stays
  deleted. INSTALL keeps the recipes that are on first and turns off a
  recipe that is on past 40. A recipe that the list holds takes the on or
  off of a new library, because the site turns recipes on and off.
- grkit_core::recipes is the record model, the file codecs, and the
  presets that the site offers (Bennet 800, Reggie Negative, and CineStill
  800T), for the site (wasm) and `grkit recipes`. It also generates the
  layout of the recipe words for the core and the installer.
- The build also reads the float settings of UserData.
- A recipe with a native look shows the native Image Control icon of its
  type.
- Save adds a recipe that is on, after the others that are on, and opens
  the camera keyboard with the automatic name; OK on that text unchanged
  keeps the automatic name. Save stops at 40 recipes on or 64 recipes. Fn
  on a recipe offers Rename and Delete. Names are up to 16 ASCII
  characters.
- On GR IV Monochrome a recipe holds its Monochrome types, no white
  balance, and no Halation color.
- The page in MENU has Enable, Options, Recipes, and Save Settings.
  Recipes lists the recipes that are on, with the mark on the current
  one. OK on a recipe opens its page with Apply, Rename, and Delete, and
  MENU goes back one page at a time. The module declares its Options as
  other modules do (options = true): they choose the recipes that ADJ
  shows. Delete asks with the confirm box of the core.
- MENU pages give their settings, their value, and their options through
  the page, so the MENU code has no page of its own. A setting of a MENU
  page can show its values on an own page with its own title and cursor,
  take OK and MENU there, or act at OK. On an own page, the confirm box of
  the core shows and takes the keys, and the keyboard returns to the page
  that opened it.

Co-authored-by: iceboerg00 <mike.graumann00@gmail.com>
The site gets a Recipes section for the selected camera line. The camera
makes and edits recipes. The site shows each one with a summary of its
settings, turns it on or off, and deletes it. As with the film looks, up
to 40 recipes are on for the camera. The site warns of a Grain or a Glow
that the package cannot apply, and of an effect that it does not have.

The list also has the presets of the site, off. Turning one on adds it,
and checks its effect. The site does not delete a preset. The name of a
recipe opens the value of each of its settings. For a preset it also
shows a picture that the camera developed from a RAW photo, with the
recipe and without it, on a comparison slider. The presets are Bennet 800
and Reggie Negative, two community Negative Film recipes for the GR III
with credit and a link to the original post, and CineStill 800T: Vision3
500T with Grain and a red Halation.

On a connected card, the site reads and writes GRKIT/RECIPES.TXT, so it
shows the recipes saved on the camera. When they differ from the recipes
of the site, the person chooses the ones to keep. One card fits GR IV and
GR IV Monochrome, so a change between them reads the recipes of the card
again. A package ZIP carries every recipe as a library, and opening the
GRKit.zip again restores them with their on or off.
The architecture overview gets a Recipes section, the card layout table
names GRKIT/RECIPES.TXT, and each README mentions Recipes.
Each description is one short sentence, at most 80 columns wide, and a
test checks the width in each language.
A recipe now holds each setting of the picture, so it gives the same
picture after any other recipe. Before, apply set only what a recipe
held and kept the rest, so the result depended on the recipe before it
and the list mark could show a recipe that the picture did not match.
The exposure settings still belong to one scene: a save holds none, and
apply keeps each one that a recipe does not hold.

- Save Settings holds Grain, Bloom, and Halation at Off when their
  modules are not loaded, as the picture then has none.
- A save while an Image Control Custom set is active holds the type and
  parameters of that set. The build reads the fields of each set and
  checks that each is one stride after the set before it.
- Each preset holds the white balance and each correction setting.
  CineStill 800T uses Auto white balance shifted to B10, which puts
  night scenes in the colors of CineStill 800T scans and keeps daylight
  usable, with shadow correction Off, peripheral illumination
  correction Off, and high-ISO noise reduction Low.
The picture of the preset is developed again with the white balance and the correction settings that the recipe now holds: Auto white balance shifted to B10, shadow correction Off, peripheral illumination correction Off, and high-ISO noise reduction Low.
OK on Undo restored the newest undo step and closed ADJ, so each further undo or the next recipe needed ADJ again. The page now keeps ADJ open on Undo, with the cursor on Undo while undo steps are left, and on the recipe that the settings match after the last one. A page can keep ADJ open for a row with the optional MenuPage::stays.
…ecipe file

Each recipe has an ID that stays with it when the recipes move, and the
recipe file keeps what U1, U2, and U3 of the mode dial do: follow, turn
GRKit off, or apply the recipe with an ID. IDs only grow, so a deleted
recipe never takes the references of another; a reference to a recipe
that is gone follows.

The camera gives a saved recipe the next ID, INSTALL gives one to each
added recipe and to a recipe without one, and the site's write gives one
to each new recipe and returns the IDs, so the site's library stays the
same as the card. One helper moves a recipe's words, name, and ID in the
core, and INSTALL holds a recipe as one record. A package library holds
no IDs and no user modes.
A recipe ID is now a generated number, so a recipe that the site moves to
another card keeps an ID that no recipe of that card is likely to have
had, and a user mode that names a deleted recipe there does not come back
to life. The camera and INSTALL take the first candidate from the generic
timer that no recipe has and no user mode names (runtime/recipe_id.h); the
site generates the ID when a recipe joins its library. The recipe file no
longer keeps a next ID, and its write keeps each ID once instead of giving
new ones: a recipe without one gets it from INSTALL at the next start.
Enable at Start, a new row after Enable GRKit in the GRKit section of
MENU, sets the switch at each start: On, Off, or Keep Last. INSTALL
applies it before it selects the modules, so Off loads each module
stopped. A camera with saved settings from an earlier GRKit gets Keep
Last, and a new camera gets On.
When the mode dial stays on U1, U2, or U3, the core applies what the
recipe file assigns to it: GRKit Off, or GRKit On and a recipe, without an
undo step. Changes there are temporary: leaving for another position
restores each GRKit setting that differs from the base state, and the
resident loader does not save the main state file while a user mode holds
it. U to U applies the next user mode at once. A start on a bound user
mode applies it once the shooting screen shows. A user mode whose recipe
is gone, off, or cannot apply follows.

The dial is part of CORE.RECIPE: its hook (point mode.dial) installs with
the Recipes module, also when it loads stopped, and it acts while the
Enable of that module is On, so Enable GRKit Off does not stop it. The
hook only restarts a timer of the App task; the timer acts once the
firmware has loaded the native settings of the position. INSTALL writes
the entry of the menu for SYSTEM_READY into the services block, which
also holds the copy of the base state.
The Recipes page of MENU gets Mode Dial, before Save Settings. It lists
U1, U2, and U3 with their values: None, GRKit Off, or the name of a
recipe. A recipe that the camera does not list, deleted or off, shows
None, as the user mode then follows. OK on a user mode shows None, GRKit
Off, and each recipe that is on, with the mark on its value. OK sets the
value and returns to the list; MENU and a half-press set nothing. The
recipe file saves the change, and while the dial is on that user mode,
the new value applies at once through the steps of a dial move.
When the core acts on a bound user mode of the mode dial, a label in the
live view shows for 2 seconds: the user mode and the recipe name, as in
"U1: Street", or "U3: GRKit Off". A line under it names each part of the
recipe that did not apply (Grain or Glow without its module), or why the
recipe cannot apply (its effect is missing, or the camera lacks a native
value). The label shows after a dial move, at a start on a bound user
mode, and after a change of that user mode on the Mode Dial page. A user
mode that follows, and a move to another position, show no label.

The label is native string views on the live-view canvas, in the font of
the native live-view text, and the text hook gives their texts in the
menu language, so each language uses its own camera font. The texts
reuse the menu strings. The framing component shows a waiting label when
a still live view shows its text, and drops it when DISP hides the text
(No Info or Off), in a movie, or when the live view ends. The menu entry
that INSTALL writes for the shooting screen (now menu_viewfinder) takes
these events. CORE.RECIPE now also needs the overlay point, so the
shooting-screen hook installs for the dial without other modules.
The Recipes section shows the user modes of the mode dial of a connected
card and lets the person set each to None, GRKit Off, or a recipe that is
on. A change of the dial alone is a card change. The recipe file takes the
dial to write (write_recipe_file) and gives it back (read_recipe_dial); a
user mode whose recipe the file does not hold follows.
INSTALL runs as a Linux process, where reading CNTPCT is an undefined
instruction. Any start that gave a recipe an ID, as the import of a
package library, ended INSTALL with SIGILL (exit 132). INSTALL now takes
the value behind new IDs from clock_gettime; the core keeps the timer.
A recipe library now sets U1 to U3 in its header: keep the camera's
value, follow, GRKit Off, or a record of the library. INSTALL applies the
steps once with the import and gives a record the ID of the recipe that
it became; a record it does not import, or a recipe that is off, follows.
The site keeps a choice for each camera line and shows it in ZIP mode.
A site write of the recipe file and its read let a user mode whose
recipe is off follow.
Save Settings on a user mode of the Mode Dial page saves the GRKit
settings in it and gives it Saved Settings, a value next to Follow,
GRKit Off, and a recipe. A set holds each capability, with the effect by
its recipe code and its Fn adjustments and Toning, and by state file ID
each saved module setting, the Enable of each module, and the switch.
Entering the user mode applies each saved value that differs, through
the setters; another position restores the base state.

The header keeps a set for each user mode, the resident loader saves
them in GRKIT/USERMODE.TXT with their own change count, and INSTALL
restores them. Recipe IDs end two below the largest value, so the new
value fits.
…tings

The mode dial snapshots, restores, and saves the value of each capability. CORE.ADJ and CORE.ADJ_MODULE say where the next ADJ opens, so a move of the dial no longer resets them and a user mode does not save them.
Recipes and the mode dial make the core and the installer larger, and the synthetic GR III fast-boot file passed the end of the RTOS code region by 53 KB. The cache of a start now holds 704 KB: the official modules and about 38 effects of the largest size. A file that does not fit reads from the card.
The ADJ button sends its own press and then the confirm of OK, so on the Recipes page it applied the highlighted recipe, ran Save Settings, or ran Undo before ADJ closed. A page of actions now acts only on OK; an ADJ press closes it, as the other ADJ exits do.
The rename test copied 7 bytes from the 6-byte string "Night", which the sanitizer check of CI reports as an out-of-bounds read.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant