Skip to content

Comments

Ram watch scripts#6

Open
hhirtz wants to merge 4 commits intoNobodyNada:masterfrom
hhirtz:ram-watch-scripts
Open

Ram watch scripts#6
hhirtz wants to merge 4 commits intoNobodyNada:masterfrom
hhirtz:ram-watch-scripts

Conversation

@hhirtz
Copy link
Contributor

@hhirtz hhirtz commented Feb 7, 2026

Following #5

This PR is still a work in progress but the bare functionality is here.

let int = mem::u16le(0xb46).to_hex();
let sub = mem::u16le(0xb48).to_hex();
`${int}.${sub}`

rip rhai highlighting

It also has a bunch of random fixes so it's probably a better read by commit.. i can open other PRs if you want.

TODO

  • fix the position of the ramwatch editor toggle between script and address panels
  • remove the scrollbar in the script editor
  • find a better way to size name/value columns since values can now span larger than a u64
  • include a link to https://rhai.rs/book/language/values-and-types.html in the UI

Would also be nice to:

  • add a warning before quitting mvi if ramwatches are modified
  • avoid executing ramwatches every host frame
  • copy and paste in the editor
  • highlighting??
  • on-the-fly linting???

Copy link
Owner

@NobodyNada NobodyNada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, thanks! Just a couple nits.

src/core/mod.rs Outdated
Comment on lines 48 to 51
input: *const [u8],
input_ports: *const [InputPort],
audio_callback: Option<*mut dyn FnMut(&[AudioFrame])>,
input: &'static [u8],
input_ports: &'static [InputPort],
audio_callback: Option<&'static mut (dyn FnMut(&[AudioFrame]) + Send)>,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were raw pointers to make it obvious that they have lifetimes not tracked by the compiler. If you're changing this to use references, please add a comment documenting that these don't really have 'static lifetimes and that we need to be careful when accessing these fields.

(As a matter of style I'd generally prefer to keep them as a raw pointers just as a reminder to be careful when working with these fields, but I'm in the middle of rewriting this whole file for the wasm port anyway, so I don't really care too much what happens to it in the meantime.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the references but kept the + Send change on audio_callback.

src/core/mod.rs Outdated
Comment on lines 304 to 316
pub fn read_memory_byte(address: usize) -> Option<u8> {
lock_opt()?.get_memory_byte(address).copied()
}

pub fn read_memory_le(address: usize, width: u8) -> Option<u64> {
let mut core = lock_opt()?;
let mut v = 0;
for offset in 0..width as usize {
v |= (core.get_memory_byte(address + offset).copied()? as u64) << (offset * 8);
}
Some(v)
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The core should not expose global state -- the design of mvi is such that all the components are modular, interact via references, and have no global state.

Core internally breaks this model due to the limitations of dynamic libraries. However, the external interface to Core abstracts this away by requiring access via references to hide the global state that exists internally. And once the wasm rewrite is complete, Core will no longer have any global state -- it will be a fully self-contained object that owns an instance of a wasm module. This will make it possible to load multiple Cores in the same process, which is something I'd like to be possible for use cases that embed mvi as a library.

I understand that having global functions simplifies the Rhai callback functions that need to access core state. I think the best way to implement this would be by using NativeCallContext::tag or similar to provide a context object that Rhai callbacks can use to access relevant state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to use the tag feature. Since tags must implement Any they must be 'static, so i used unsafe to extend the lifetime here:

https://github.com/NobodyNada/mvi/pull/6/changes#diff-0a108025772ad59132dfb3e916df6cdc2cd52325f8d89e0b3ba9270eb5122088R79

A cleaner option would be to wrap Tas.core into an Arc and a Mutex but it's more boilerplate. I can make the change if you want.

Comment on lines +17 to +21
/// `true` if script must be used instead of address and format
use_script: bool,
address: String,
format: movie::RamWatchFormat,
rhai_script: String,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be factored out into an enum to avoid data redundancy? Maybe this could even just be a RamWatchValue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editor contains both address/format and the rhai script to remember values in text fields and radio buttons when the user switches between the editor modes.

Since `CoreImpl` is `Send`, `audio_callback` must also be `Send`
this runs the library deinitialization
Before, since `reported_error` wasn't set to `None` on close, the popup
would reopen every time.
This allows users to enter complex expressions in the RAM watch editor,
using the rhai scripting language

For example, showing samus' speed in hex values:

```rhai
let int = mem::u16le(0xb46).to_hex();
let sub = mem::u16le(0xb48).to_hex();
`${int}.${sub}`
```
@hhirtz
Copy link
Contributor Author

hhirtz commented Feb 12, 2026

Updated the design of the editor. there is now a radio button to switch between the modes:

screen-20260212194827 screen-20260212194846

@hhirtz hhirtz marked this pull request as ready for review February 12, 2026 19:30
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.

2 participants