Changelog:

Add clarification on binaries from GitHub Actions.
Back to development mode.
Highlight known symbols in memory hex view
Added support for loading symbol files generated by WLA-DX
Added unit tests to check the WLA-DX symbol import.
Fixed an error in the unittest for WLA symbols and slightly modifiedthe detection of the format
#1747 Add support the MAP file output by the Z80ASM from Z88DK
Issue #1754 Bad emulation of VRAM access timing with screen disabledon MSX2

TODO still needs testing.
Throttle ImGui messagesWhen some Tcl script is generating warnings at a too high rate the GUI
could become unusable. It could even be so bad that the only way to
recover was to kill openMSX.

For example:
debug set_bp 0x38 bla
(“bla” is an invalid Tcl expression, and this gets evaluated every IRQ,
50 times per second)

In this patch we throttle the messages if there are too many of them in
a too short timespan. At the moment I picked:
* more than 5 within a second
* or more than 10 within a minute.
All the latest messages are still shown (same as before) but during
throttling we don’t re-focus the message window or show any (modal)
popups.

This patch is just a proof-of-concepts. The detail of how exactly we
throttle can still be fine-tuned.
Add context menu with ‘Show in Disassembly’ entry to addresses in breakpoints window.
Merge branch ‘zappatic-breakpoint-jump-to-disassembly’
fix: imgui demo window fades out together with main menu barEasily fixed once the problem was known.
More direct way to test if main menu bar is hoveredSee
#1756
Menu bar doesn’t (reliably) appear on full screen in Windows, in contrast to Linux #1756

We only tested whether the main menu bar was hovered in an very indirect
way: check if any window is hovered. But this relies on an
implementation detail: the main menu bar is internally implemented as an
ImGui window.

In this patch we more directly check the mouse coordinates. Maybe that
solves the windows/fullscreen issue???

But as a bonus this approach allows to _fully_ fade out the menu bar.
Before we only faded out till alpha=0.001. In practice this is
invisible, but because it’s not exactly zero, it technically still gets
drawn (and that was needed for the (old) window-is-hovered check).
Cassetteplayer: added ‘setpos’ subcommandTODO make it available in the GUI.
Allow to call ‘cassetteplayer setpos’ from GUIFollow-up on 9791f02.
Add tooltip for tape position indicator.As it is now also editable.

Closes #1725 together with 9791f02 and 95d6b54.
Add question about two LED/icon bars and fix h-level.
Upgrade SDL2 to 2.30.7.
Update Tcl to 8.6.15.
Update libPNG to 1.6.44.
Print extra info in tile-viewerRequest via issue #1759:
Missing information in new tile viewer, compared to old debugger
#1759
Update FreeType to 2.13.3Apparently we need to add the SVG rasterizer to compile on Windows. I don’t
want to bother to figure out why.
DebuggableEditor: fix crash when clicking in the datatype dropdown list (in data-preview pane)
Abbreviate ‘channel’ to ‘ch.’ to save space.I planned to add a tooltip to the column header, but I wasn’t able to get that
working.
Do not persist the freq_lock setting.For details see the issue.

Closes #1729.
Run auto-run on rewind instead of insert tape.This will make sure that at boot the tape is not reinserted. That was a bad
idea, because it will make it impossible to reset and continue loading a next
item on the tape. A real MSX also doesn’t rewind the tape when resetting it.

Fixes #1724.
Upgrade Dear ImGui to v1.19.3 (from v1.91.0)
Allow speed settings smaller than 1 (float value).This does break updates from openMSX to the Catapult slider. But that’s it, the
display value is still correct, and control still works towards openMSX.

At the same time, improve the control in the GUI:
– use one digit at most
– use logarithmic slider

Fixes #1742.
Fix (runtime) ImGui warning about duplicate IDsNewer Dear ImGui version now checks for this. When hovering over widgest
with duplicate ID, you now get a popup with a warnings and all widgets
get a red border.

In this specific case the duplicate IDs (the ID was 5 times an empty
string) didn’t cause any harm. But it’s good to avoid anyway … it
would have caused very weird behavior if we wanted to extend the
functionality in any way.
Fixed missing change from earlier commitSee commit 3285e4f
Add motorcontrol to tape deck window.Query the current status directly from the cassette player.

At the same time, we also use CassettePlayer directly for queries in the Tape
Deck window and Media menu. Should be much more efficient.

Fixes #1734.
Merge branch ‘MBilderbeek-master’
Issue#1780: Toolbar buttons have inconsistent sizes and shapes#1780

I never noticed this before, but after reading the ticket I do see it
and now it annoys me 🙂

The underlying technical reason is that these icons are actually glyphs
in a (custom) font. Though these glyphs have slightly different sizes.
And I didn’t find a way to create a ImGui::ImageButton() where the size
of the button is not directly controlled by the size of the image. E.g.
center a smaller image in a larger button.

As a workaround, I now calculate the largest size (in X and Y direction)
of all icons, and then stretch (all) icons to that common size. Though
this makes (some) icons (slightly) blurry. It’s not ideal, but at least
IMHO it’s already an improvement. For the real solution someone (not me)
will have to create new glyphs.
HQCommon: prepare for sizes other than 320This is only a preparation, by itself this patch doesn’t have any effect
(yet).
HQCommon: optimize RGB-shift positionsNow that we only have a fixed renderer, with a fixed pixel-format, we
can replace the variable RGB shift positions with pixed positions.
Making the “hq” scaler a little bit faster (has no effect on “hqlite”).
Refactor gl::PixelBuffer, replace width/height with sizeBefore PixelBuffer represented a buffer of ‘width x height’ number of
pixels, so a buffer with a particular shape. Though in fact (at the
openGL level) this is just a 1D buffer. For example a buffer of 2000
pixels can hold an image of 40 x 50 pixels, but just as well an image of
20 x 100 pixels. And also smaller images like 20 x 20.

In a future patch (to generalize the hq-scaler to more than 320×240) we
want to reuse the same PixelBuffer for multiple shapes. So instead of
allocate one for each shape, we allocate only one that can hold the
largest shape.

This patch also changes the ‘mapped()’ method to return a ‘std::span
instead of a raw-pointer ‘T*’. This makes the API more descriptive (and
simplifies some caller code). And it also makes it safer: we now have
(optional) out-of-bounds checks.

The ‘getOffset(x, y)’ method is removed. It no longer makes sense now
that the buffer no longer has a specific shape. Also for cache
efficiency it’s better to as much as possible reuse the same region in
the buffer, so typically the start of the buffer, and that’s already
available via the above `mapped()` method.
PostProcessor: share ‘pbo’ for all line-widthsThe previous patch made PixelBuffer (PBO) shape-independent. This makes
it possible to in this patch reuse the same PBO for all line-widths.
Make opengl scalers work with both 320 and 640 width screens PR#1761This commit is heavily inspired by
ttps://github.com//pull/1761
Thanks to a lot to balyuf, both for reporting and creating the initial
solution.

Summary (more details in the above link):
The ‘hq’, ‘hqlite’ and ‘ScaleNx’ used to work in ‘screen 7’ with the old
‘SDL’ renderer (work as in: they don’t fallback to the default scaler).
They never worked with the ‘SDLGL-PP’ renderer. We did remove the ‘SDL’
renderer, so in a way this can be seen as a regression.

The ‘SDL’ version of the hq{lite} scaler had special code for scaling
the X-dimension by half the amount of the Y-dimension (and that’s what
happens in ‘screen 7’ non-interlaced modes): The effect is as-if the
full hq-scaler output is calculated, and then take the average of all
pixel-pairs. Instead this implementation only calculates every other
output pixel. We may still want to change this in the future.

The main differences between this commit and the approach taken in
PR#1761 are:
* This also works for gfx9000 modes, and then specifically B7 (1024
pixels wide).
* Instead of having separate buffers/textures for width=320 and
width=640 (and after the previous point also width=1280), we only have
one buffer/texture with the maximal size (and then maybe only partly
use it).
Issue#1780: Toolbar buttons have inconsistent sizes and shapesFollow-up on 459f221.
Inspired by: #1782
Thanks ‘gilbertfrancois’ for the idea and discussion.

The remaining problem in 459f221 was that (some) icons got
stretched (and not by the same amount in X and Y). Because of that
(some) icons looked blurry.

Instead of using ImGui::ImageButton() (or ImGui::Button() with the glyph
as text), this patch use our ‘ButtonWithCustomRendering()’ helper
function to take full control over how the icon gets rendered.
Invalidate read cache when switching between CP/M and DOS ROM types.Fixes #1783.

Apparently the caching was always broken, but worked by accident. Until the
cache code was optimized via dbc32c1
about 5.5 years ago… Apparently no one uses this device, as it wasn’t
reported earlier…
Tell ImGui to leave our cursor alone when hiding it.Fixes #1769.
Add newer version of the ROM for Chakkari Copy.
Make opengl scalers work with both 320 and 640 width screens PR#1761This is a follow-up (bugfix) on 1afaa52.

I spend _a_lot_ of time debugging this (+5 hours). But in the end the
fix was very simple. (We were using the wrong version of the
offsets/weights textures, the textures for the wrong scale-factor).
Make opengl scalers work with both 320 and 640 width screens PR#1761Was still wrong from scale_factor=2 and 3 (I only tested with 4, that
worked fine).
Thanks again @balyuf for testing.
Fix shader compilation error (on windows)We had:
float pi = 4.0 * atan(1.0);
This patch replaces that with
const pi = 3.1415927;

The former gave the following compilation error on windows (or at least
in some configuration, might also depends on the specific openGL vendor
driver etc).
Unary operation not folded into constant

Thanks to @balyuf for investigating. You can find more details here:
#1761
ImGuiSpriteViewer: take sprite-magnification into account for bounding-box

Easy fix once I was aware of the problem.

See:
#1794
https://msx.org/forum/msx-talk/development/on-magnified-sprites-or-function-and-1px-offset
https://www.msx.org/forum/msx-talk/openmsx/please-help-testing-upcoming-openmsx-release?page=122 (post by Pat)
Fix deleting savestates.This was broken after 078e8f5 (oops).
[1/11] List available savestates with C++ code only, like with replays.Preparation to make it easier to show more information about the states in the
menu.

Also: define the savestate file extension and folder in one place, at least
within this file. (There’s no obvious place in our non-GUI code to put it…)

This change also changes the behaviour: if there are no savestates, the menu
item is not disabled anymore. In a later commit we will restore something
similar, but easier to understand: we explicitly tell no savestates were found.
[2/11] Do not recreate the list of savestates/replays each frame.Instead, cache it until the menu is reopened.
[3/11] Show in the menu that no states or replays are found if so.Fixes the regression that we just showed an empty menu instead of disabling the
menu item. Now it is clearer what is going on.
[4/11] Show savestates sorted on time, newest first.
[5/11] Show replays sorted on time, newest first.
[6/11] Use table instead of listbox for replays to show time.
[7/11] Display date/time in the load savestate submenu.The duplication will be mostly solved in the next commit.
[8/11] Remove most of the duplication between loadstate and loadreplay.By:
– using the same struct for both
– factoring out the selection table flags
– factoring out the way to set up and sort the columns

The formatting of the date/time was already factored out.
[9/11] Make the loadstate/loadreplay tables narrower.They were way too wide.

Accomplished by showing only the date or only the time (when it’s made today).
The full date/time is shown in a tooltip. Also made a tooltip with the full
name, so we can make the name column narrower without worrying about long names
not being readable.

To avoid double calculations with the time/date functions, we already convert
to std::time whilst scanning for files.
[10/11] Tweak some texts regarding preview.- show “No preview available…” if that’s the case
– don’t add useless texts above the list and preview when available
[11/11] Factor out more common code between loadstate/loadreplay.
Update ‘Dear ImGui’ from ‘v1.91.3’ to ‘v1.91.5 WIP (oct 28)’
Apply various (minor) suggestions from SonarCloud
Apply various (minor) suggestions from SonarCloud
SonarCloud: make overloaded operators hidden friendsSee here for why that’s better:
https://rules.sonarsource.com/cpp/RSPEC-2807/
Partial revert of previous commit (gcc workaround)The code was correct, it worked with clang, msvc and gcc-13. But not
with gcc-11 and gcc-12.
Remove ‘hqlite’ scaler algorithmIt was added as a more light-weigth version of the ‘hq’ algorithm
(instead of checking if colors are similar it checks if colors are
equal). 20 years ago that was important, but nowadays not so much. Or
better said: the extra quality is more important than the speed.

Though the main motivation for removing ‘hqlite’ is to simplify our code
base (just a little).
Remove ‘fast’ resamplerFast but low quality (can cause horrible aliasing effects). But current
computers there’s no reason anymore to still use the low quality
resampler.

But the main motivation for removing it is to simplify our code base (a
little bit).
[pre-1] Added inplace_buffer and small_bufferIn this patch series I want to get rid of Variable Length Arrays (VLA).
These are arrays with a size that’s only known at run-time (thus
variable length). And they are placed on the stack. Meaning that also
the stack frame has a variable length. Typically to make this possible
the compiler introduces a ‘(stack-)frame-pointer’ (to be able to access
other local variables that may also be allocated on the stack), and
usually this takes up a general purpose register. So VLAs are not free.

Though the main motivation for wanting to remove VLAs is:
* clang is getting more aggressive in generating warning on VLAs
* VLAs were never part of C++, but gcc/clang support them as an
extension, msvc does not and there we used workarounds.
* VLAs are ‘dangerous’ in the sense that you can come up with scenarios
that will overflow the stack. Especially on windows which has by
default a smaller stack than Linux (typical: 1MB vs 8MB).

This patch is only a preparation. It introduces two new helper classes:
* inplace_buffer: this is a run-time sized array with a known upper
limit for the size. This array is allocated on the stack.
* small_buffer: this is also a run-time sized array, but we only know a
typical size, if the actual size is larger then we fall-back to
heap-allocation.
See comments in the code for more details.

These are yet two new array-like classes. Maybe it’s good to give an
overview of classes we have in openMSX:

* std::array:
A fixed sized array. Allocated on the stack. Size must be known at
compile time. If possible prefer this type, it’s the most efficient.

* dynarray:
Dynamically sized array at construction, but after construction the
size can no longer change. Storage is allocated on the heap.

* std::vector:
Fully dynamically sized array. Allocated on the heap. Can grow/shrink
in size at any time (and internally keeps track of spare capacity to
make this efficient).

* static_vector:
A dynamically sized array with a (fixed) upper bound in size.
Allocated on the stack. The object itself contains storage for N
elements, even if only a few elements are actually used. After
construction the size can still vary (e.g. you can still add more
elements).

Note: something like this might become available in future c++
versions as std::inplace_vector (and ‘static_vector’ was the old
proposed name).

* inplace_buffer:
This is a mix of ‘dynarray’ and ‘inplace_vector’. The size can no
longer change after construction. But instead of allocating on the
heap this one is allocated on the stack. You must specify a static
upper-bound for the size.

Optionally the content of the buffer can be left uninitialized.

* small_buffer:
Similar to ‘inplace_buffer’. Up-to N elements are allocated in the
object itself, but if at-run-time the size is larger than N, this
class falls back to heap-allocation.

Optionally the content of the buffer can be left uninitialized.

* MemBuffer:
Allocated on the heap. Does not keep track of it’s own size. Of all
the classes in this overview, this is the only one that allows to
specify an alignment.
Note: maybe we should deprecate this and replace it with dynarray?

All these classes make different trade-offs:
* heap-allocation vs stack-allocation
* resizeable after construction or not
* initial content can be left uninitialized or not.
[pre-2] Only use UNaligned SSE load/store intrinsicsFor example replace:
_mm_load_si128()
with
_mm_loadu_si128()
The former requires a 128-bit aligned pointer, the latter doesn’t have
this requirement.

When SSE was first introduced, the former instruction would execute
faster. But on modern CPUs both instructions execute:
* Just as fast when the given pointer is actually aligned.
* Just as fast when the pointer is not fully aligned, but does not cross
a cache-line boundary (I mean the 128-bit element starting at the
given pointer).
* If the element does cross a cacheline or a page, then there might be a
performance penality (for aligned accesses such crossings can never
happen).

So nowadays there’s much less need to use aligned load/stores. And
using the unaligned versions does allow some simplifications in the rest
of the code (see next patches). Nevertheless compiler still try to align
large buffers. So in practice the unaligned load/store instruction will
still operate on aligned address (IOW it’s still likely but no longer
100% guaranteed).

This is a preparation to be able to get rid of
VLA_SSE_ALIGNED
This alignment was useful in the past, but much less so nowadays.
[1/n] Printer: replace VLA with small_buffer
[2/n] SettingsManager: replace VLA with tmpStrCat()In all practical cases the string will fit in the internal
‘TemporaryString’ buffer, and then there’s also no heap allocation.
[3/n] SoundDevice: replace VLA with inplace_buffer
[4/n] TclObject: replace VLA with small_buffer
[5/n] windows wstring conversion, replace VLA with {w}string
[6/n] SRAM: replace VLA with small_buffer
[7/n] AviWriter,WavWriter: replace VLA with small_buffer
[8/n] AviRecorder: replace VLA with small_buffer
[9/n] GLUtil: replace VLA with std::stringThis might do an extra memory allocation, but anyway only used for error
reporting.
[10/n] PNG: replace VLA with small_buffer
[11/n] PostProcessor: replace VLA with inplace_buffer
[12/n] VisibleSurface: replace VLA with small_buffer
[13/n] MSXMixer: replace VLA with inplace_buffer
[14/n] Resamplers: replace VLA with small_buffer
[15/n] Deflicker: replace VLA with inplace_buffer
[16/n] FrameSource: replace VLA with inplace_buffer
[17/n] SuperImposedFrame: replace VLA with inplace_buffer
[18/n] GLHQScaler: replace VLA with inplace_buffer
[final] Remove vla.hhThe previous patches in this series removed all uses of VLA. This patch
removes the (now no longer used) ‘vla.hh’ header file.
gl_vec: fix -Wshadow warnings (clang)
more (clang) compiler warning fixes
workaround clang (pre-16) compiler errors
Workaround(?) msvc compilation errorProbably caused because we’re still using our own view::transform (not
std::views::transform, because we can’t yet used that) and that is not
100% correct, thus not fully compatible with std::ranges::subrange.
Or in other words: in the future we can remove these workarounds again.
[1/3] Put CassettePlayer command outside CassettePlayer class.
[2/3] Also instantiate cassetteplayer command for DummyCassettePort.This way, there is a clearer error message when using cassetteplayer commands
in a system without cassette port.

Closes #1793.
[3/3] Rename tapeCommand to cassettePlayerCommand.
[1/3] Extract ‘XSAExtractor’ class from ‘XSADIskImage.cc’The goal is to reuse this part in a ‘xsa2dsk’ standalone utility.
[2/3] Made XSAExtractor less dependent on openMSX typesReplace:
File -> std::span
MemBuffer -> std::vector

It’s not fully independent of openMSX. E.g. it still uses ‘SectorBuffer’
and ‘MSXException’. But maybe (for now?) that’s acceptable.
[3/3] Added standalone xsa2dsk toolMaybe in the future we can remove support for xsa disk images from
openMSX itself.
Fix(?) windows-specific bugs introduced in VLA refactoring
Fix assert when muting individual sound-channels
Improve individual channel settings window- use table headers
– tweak sizes
CircularBuffer: rename methods to defacto-standard STL-names
MSXMixer: replace clock.setFreq() with clock.setPeriod()The latter is a more direct way, it has one less intermediate rounding
error. Though I verified: for frequency=44100 and samples=512 the final
result is identical.
Fix/update unittest after 61f6f03
Apply sonar-cloud suggestion: prefer std::begin()/end() in generic codeSee
https://rules.sonarsource.com/cpp/RSPEC-6024/
Resolve sonar cloud remark about explicit constructor/conversion-operator

Before we added a comment /*implicit*/ to document the missing
“explicit” was intended. Since c++20 you can ‘calculate’ whether or not
the function should be explicit. And with this “explicit(false)” has
become a defacto-standard way to mean “implicit”. It means exactly the
same as no annotation at all, but it does make the intent clear: it’s
intended like this, we did not simply forget about it.
Fix regression that broke loading states/replays.Apparently I didn’t properly check after
294f872 (the last in that patch series)…
oops. Fixed now.
Bugfix in circular_buffer + extend unittestCalculating the difference between two iterators gave the wrong result
(inverted).

We never hit this bug, till now (in Quibus’ PR that adds a recently used
machine list).
Allow to open multiple bitmap/tile/sprite viewersThis implements a large part of:
Be able to open multiple debug windows of the same type
#1699
Minor corrections on ROM and RAM id’s for consistency
[1/3] Move addRecentItem (in generalized form) into ImGuiUtils.So that it can be used from other places as well.
[2/3] Keep recent items of machines and be able to select from them.The resulting duplication between recent items and normal selection will be
resolved in the next commit.

Closes #1697.
[3/3] Factor out common code between recent and available machine list.
Simplify MemSet and MemSet2We had manually unrolled these functions using SSE2 intrinsics. This
commit replaces that with plain c++ code. The greatly simplifies the
code.

In the past our tuned versions were faster, but I verified that new gcc
versions generate quasi equivalent code for both. In other words: newer
gcc versions can perform the same optimizations themselves. Moreover
when compiling for AVX2 or AVX512 the compiler can take advantage of
that, while our manually tuned code is stuck with SSE2.
Remove MemSet, simplify MemSet2After the previous patch MemSet became equivalent with ranges::fill(),
so we can just as well use that directly.

Also renamed MemSet2 to fill_2() and made it a regualr function instead
of a class with operator() (we no longer need to instantiate this class
for different Pixel-types).
Extend MemBuffer with sizeBefore MemBuffer internally only kept a pointer to the allocated memory
block. This patch extends that with a size member variable.

This makes MemBuffer objects a bit more heavy (sizeof(MemBuffer)
increases from 8 to 16). Though often (not always):
* We manually kept track of the size in some other way (future patches in
the series will then eliminate those).
* The MemBuffer object is a local variable, and then the compiler can
usually eliminate the extra size member (if indeed unused).

This size member allows to add (optional) bounds-checking in MemBuffer.
And it allows to (correctly) convert MemBuffer into a std::span, this
also allows for better bounds and buffer-overflow checks.

More in detail, this patch extends MemBuffer with these convenience
methods:
* size() and empty()
* begin() and end()
* front() and back()
* operator[] with (optional) bounds-check
* conversion to span, first(), subspan()

This brings MemBuffer a bit closer to std::vector. The remaining
differences are:
* std::vector is still a bit more heavy weight. Typically sizeof(vector)
== 24, sizeof(MemBuffer) == 16.
* MemBuffer keeps the initial content uninitialized. std::vector always
initializes, even if the buffer will soon after be overwritten (e.g.
by reading from a file).
* Because of this it’s only allowed to use MemBuffer with trivially
copyable types (copy is equivalent with memcpy). This patch adds
such a check.
* On destruction MemBuffer just frees the memory block. std::vector will
first properly destruct all elements it contains. But it’s possible
the destructor of those elements is trivial (does nothing), then of
course std::vector also doesn’t need to do anything extra.
* Because of this it’s only allowed to use MemBuffer with trivially
destructible types. This patch adds a check for that.
So the remaining difference are still sufficient to warrant the
existence of MemBuffer (we cannot just replace it with std::vector and
keep the same performance).

This change in MemBuffer allows for various simplifications. But that’s
left for (multiple) follow-up patches.
Simplify usage of MemBuffer in ReverseManager and OutputBuffer
Simplify usage of MemBuffer in SettingsConfig,XMLDocument
Simplify usage of MemBuffer in Debugger,MSXtar,RamDSKDiskImage
Simplify usage of MemBuffer in CompressedFileAdapter,ZlibInflate,FileBase
Simplify usage of MemBuffer in FilePoolCore
Simplify usage of MemBuffer in Ram
Simplify usage of MemBuffer in Rom
Simplify usage of MemBuffer in ResampleHQ
Simplify usage of MemBuffer in SDLSoundDriver
Simplify usage of MemBuffer in WavData
Simplify usage of MemBuffer in Base64,HexDump
Simplify usage of MemBuffer in DeltaBlock,TigerTree
Simplify usage of MemBuffer in PixelBuffer
Simplify usage of MemBuffer in RawFrame
Simplify usage of MemBuffer in ZMBVEncoder,V9990CmdEngine
Show page in bitmap viewerIf you selected ‘All’ for display page in the bitmap viewer then the y
coordinate was a number in the range [0,1023].
This commit will show the y coordinate as a number in the range [0,255]
and display the page as a separate item.
Apply clang-tidy ‘modernize-use-auto’ suggestionsE.g. in cases like:
unsigned u = narrow(…);
where the type (‘unsigned’) is repeated twice in the same line.
Apply clang-tidy ‘modernize-min-max-use-initializer-list’ suggestionsReplace
std::min(std::min(a, b), c);
with
std::min({a, b, c});

And similar for std::max();
Apply clang-tidy ‘modernize-use-emplace’ suggestions
Apply clang-tidy ‘modernize-use-starts-ends-with’ suggestions
Apply clang-tidy ‘modernize-pass-by-value’ suggestions
Small tweak on c9533bcThat commit adds the text “page=n” (with ‘n’ a digit 0-3). Because ‘n’
can vary we want to show it in a monospace font, otherwise the text that
follows on the same line can shift around.

I discussed this with David (turbor). Initially we thought it was fine
to show the full text (page=n) with the same monospace font. Though now
when I actually see the result, you can notice the difference in font
between “page=” and the other text (non-digits) on the line.

It’s a detail, but let’s fix it anyway.
Apply clang-tidy ‘bugprone-unused-local-non-trivial-variable’ suggestions

Was not a bug, but a needless/unused calculation. Probably a left-over
from some refactoring.
Apply clang-tidy ‘bugprone-suspicious-stringview-data-usage’ suggestionsI think these were correct, but indeed suspicious. Rewrote it to more
more robust and more obviously correct.
Refactor interaction between rapidsax and XMLElementTriggered while investigating the clang-tidy suggestion
‘bugprone-suspicious-stringview-data-usage’.

Our XML parser (rapidsax) calls various handlers with std::string_view
parameters, e.g. to pass the name of an XML-tag. Optionally we can
request to zero-terminate those strings (this happens in-place in the
memory buffer containing the XML file).

For example in XMLDocument::load() we request such zero-termination. It
has a callback function
void start(std::string_view tagName)
That callback uses ‘tagName.data()’ and then (indirectly) passes that to
the XMLElement constructor which takes a ‘const char*’ parameter. This
parameter is expected to point to a zero-terminated string.

In general that’s a suspicious operation: in general
std::string_view::data() may not point to zero-terminated data. And
that’s why the clang-tidy gave a warning on it.

In this specific case we know that the std::string_view points to a
zero-terminated string. Thus all is fine. But it’s always nice to
express (and verify) such guarantees/constraints via the c++ type-system
(so that you get a compile-error when you violate the constraint).
That’s possible by changing the type from ‘std::string_view’ to
‘zstring_view’. (Note: we only do this when we do request
zero-terminated strings, we don’t always require that, and then we
continue using ‘std::string_view’).

However, while implementing this change (string_view -> zstring_view), I
noticed we do actually violate this constraint: we do pass
NON-zero-terminated strings to the start() callback!!! Or at least we
temporarily violate it. Only some time after the callback returns we do
add the zero-terminator.

So in the end it worked fine, but nevertheless it was very brittle code.
So this commit also ensures that we zero-terminate BEFORE calling the
callback functions. This has a (small) cost in rapidsax::parseElement(),
but that’s an acceptable trade off for the cleaner semantics / safety
guarantees.
Add a few asserts before usage of std::optionalTriggered after investigating some clang-tidy
‘bugprone-unchecked-optional-access’ warnings.

I believe all code was correct. Adding an assert documents we have
indeed verified it.
Apply a few of clang-tidy ‘bugprone-implicit-widening-of-multiplication-result’ suggestions

This clang-tidy warning triggers e.g. when you multiply 2 32-bit values
together (the result is still 32-bit, thus it might overflow) and then
convert the result to 64-bit (which could hold the result without
overflow).

The ‘fix’ is to first convert (at least one of) the operands to 64-bit
and then perform a 64-bit multiplication(*).
(*) So in C++ you do a ’64-bit x 64-bit -> 64-bit’, but the compiler
may turn that into ’32-bit x 32-bit -> 64-bit’ if that’s more
efficient on the target CPUi (e.g. on x86).

Even if in practice there’s no risk of overflow it may still be
beneficial. Consider this example:
myVector.reserve(myUint32 * 2);
Suppose _we_ know myUint32 is always small, so the multiplication will
never overflow. But _the_compiler_ may not know this (and/or take this
into account). So it still has to generate code as-if overflow _could_
happen.

On a 64-bit CPU the variable ‘myUint32’ is likely stored in a 64-bit
register. So the multiplication by 2 (or shifting) does not
(necessarily) automatically truncate this to 32-bit. So the compiler
does need to insert an explicit instruction to zero the 32 upper bits
before it can be passed to the reserve() function (which does take a
64-bit input).

If instead we would have written this code:
myVector.reserve(myUint32 * size_t(2));
We both avoid the potential overflow, and we possibly save one
instruction.

So the ‘bugprone-implicit-widening-of-multiplication-result’ warnings
seems like a good idea. Unfortunately in its current form they produce
_way_ too many false positives.

For example it also triggers on code like this:
std::array myArray;
This indeed does an implicit widening of a 32-bit multiplication to
64-bit. But in this case that perfectly fine. We’re very sure there is
no overflow here 😉

So unfortunately we had to ignore most of these clang-tidy warnings.
This patch only applies the very obvious ones. (And it likely misses
some, the signal-to-noise ration is just too high).
Apply some clang-tidy ‘performace-*’ suggestionsMore specifically:
performance-trivially-destructible
performance-unnecessary-copy-initialization
performance-unnecessary-value-param

All were very minor effects.
Apply some clang-tidy ‘misc-use-internal-linkage’ suggestions
Replace horizontal/vertical selector in ImGuiOsdIconsBefore this patch you could select between a horizontal or a vertical
layout for the OSD icons. This patch removes that selector and just
fills the available window space row-by-row. You obtain a vertical
layout by making the window very narrow (so that only 1 icon fits per
row). I believe this idea was once suggested by ‘Vampier’.

This does make a tradeoff:
* Before it was possible to control the spacing between the icons (by
making the window wider/taller than needed). That’s no longer
possible.
* But now it’s possible to arrange the icons in more than one row.

So this is an experiment. Let’s see how it goes.
Fix clang compiler error in GLUtil.hhIntroduced in 3435d23.
This should not have compiled in any compiler, but nevertheless it did
with both gcc, msvc, and (older) clang versions. clang-19 caught it.

The method containing the error was likely never called.
Fix several clang -Wshorten-64-to-32 compiler warningsHarmless, but good to fix anyway.
Experimental: added VDP-block-command-overlay in ImGuiBitmapViewerThis implements:
#1804 suggestion: show VDP commands in ImGuiBitmapViewer
#1804

Still needs lots more testing. Very likely there are still bugs. But
feedback is already very welcome.
Added apple-clang-16 workaroundI verified that it _does_ work with a normal clang-16.
Fix (=remove) assertion about alignmentA little while ago we no longer strictly align (some) buffer to 16-byte
boundaries (for x86 SSE instructions). See commit fc04f34 and
follow-ups for the rationale.

Though we still had a few asserts in our code that do check for this
stricter alignment. It turned out that this assert still passed when
compiled with gcc, but not with clang. Apparently gcc figures out it’s
still a good idea to keep large buffers 16-byte aligned (or it could
just be a coincident).

Anyway, removing the assert fixes the problem. And we could cleanup some
more alignment-check related code as well.
Update bank registers of MFR SCC+ SD to 9-bit.Closes #1808.
Tweak BreakPointBase::getCondition() and getCommand()Before we had two versions of each:
* getCondition() and getConditionObj()
* getCommand() and getCommandObj()
The former returns a string, the latter a TclObject.

Though for all callers that query the string it was actually more
efficient to instead query the TclObject (e.g. because afterwards the
string is converted back to a TclObject). This is probably a left-over
from when TclObject was less flexible.

So in this patch:
* We change all callers to use the ‘obj’ variant.
* We remove the non-obj variant.
* We rename getConditionObj() to getCondition() (and same for getCommand()).
Added flash ROM type: SST39SF010Will be used later in DalSoRi R2.
Make it easier to (un)register multiple IO ports* Both ‘in’ and ‘out’ at the same time.
* And/or a range of ports at the same time.
Allow to specify an id-attribute for the initial flash content in theconfig file

By including a section like




in the config file of a MSX device it’s possible to use that rom as the
initial content for the flash rom. This is inly for the first time that
device is started. The next time it’s started it uses the last, possibly
re-flashed, content.

Though this is ambiguous when the MSX device contains multiple roms. A
concrete example is the DalSoRiR2 device (which we’ll add soon). It
contains both a flash rom (for the MSX-AUDIO BIOS) and the OPL4
sample-rom.

This patch allows to (optionally) specify an “id-string” for the flash
content. Then only the config section with corresponding id will be
taken.



Or when no rom-tag with matching id is present in the config file, then
no initial content is loaded (initial flash content is all 0xff).
Move YMF278B specific knowledge out of MSXMoonSound classThe OPL4 (YMF278B) chip has two main parts:
* The FM-part, this is implemented in the YMF262 class.
* The wave-part, this is implemented in the YMF278 class.
Both parts are mostly, but not fully independent.

Before this patch a lot of the glue-logic that ties both parts together
was implemented in the MSXMoonSound class. This patch moves that logic
to a new class YMF278B.

The main motivation for this is that we want to add a new MSX device
DalSoRiR2 which also contains a OPL4 chip. And we don’t want to
duplicate all that glue-logic.
Made YMF278 independent from MoonSound-specific memory layoutThe MoonSound cartridge has a 2MB ROM and a variable amount of RAM
connected to the OPL4 chip (in a specific way, see code for details).
Currently that knowledge is hardcoded in the YMF278 class.

We want to add the DalSoRiR2 device. That one also uses a OPL4 chip, but
it has the memory connected in a different way.

This patch makes the YMF278 class independent from the specific memory
layout. More specifically devices using the OPL4 chip must pass a
callback that is responsible for creating the specific memory layout.
This must be callback, and not some static setup because the YMF278 can
dynamically switch between two memory modes (see code for details).
Added DalSoRiR2 deviceLargely implemented by Manuel Bilderbeek, I only did some refactoring
and small fixes.

The main difference with MoonSound are:
* This has 4MB sample RAM and 2MB sample ROM. The OPL4 can only address
4MB memory. Therefor DalSoRiR2 allows to switch between 2MB ROM + 2MB
RAM, or 4MB RAM
* There is a 128kB flash ROM. This is meant for a MSX-AUDIO BIOS.
* The MSX-AUDIO BIOS requires extra RAM, so DalSoRiR2 has 32kB RAM.
* The OPL4-FM-part can be dyncamically configured to listen to IO-ports
0xC0-0xC3 and/or 0xC4-0xC7.
* There are 4 DIP switches to configure various stuff.

See code for lots more details. Or see the user manual here:
https://drive.google.com/file/d/1xmYmKCZYfbjxOh9NBBrQIZ5-gYrYr5zV/view
Merge pull request #1810 from openMSX/DalSoRiR2DalSoRiR2, based upon PR#1809 by Manuel
Show hint about setting the default machine……when it is already running the default machine.
Fix debug build / add optional_fixed_span utilityIn the YMF278 code we divide the 4MB sample address space into 32 chunks
of 128kB. For each of these chunks we store a pointer to the
corresponding mapped memory (ROM or RAM, possibly mirrored) or nullptr
in case that chunk is unmapped.

Though instead of storing a raw pointer we store a
std::span
indicating it points to a 128kB chunk (a raw pointer does not indicate
how large the pointed to memory block is). And internally a fixed size
span also stores just a pointer. So far so good.

The problem is when we want to indicate an unmapped memory region. An
invariant of std::span is that it must _always_ points to a valid
range of N elements. But we can try to ‘trick’ the compiler via an
initialization like:
std::span{static_cast(nullptr), N};
That compiles, and actually runs fine. And we can check the invalid
state via something like:
data() == nullptr
However the debug-STL-mode in gcc verifies several invariants, including
the one that a ‘span‘ must point to a valid range. And thus that
triggers an error on the above initialization.

To fix this, and keep the same efficiency, we introduced the
‘optional_fixed_span‘ class:
* It can only be constructed from
– a valid std::span
– or to the empty state
* Internally it stores a single pointer.
* And the only operation on this class is: convert it to a
std::optional>
* This enforces the check for nullptr (via std::nullopt).
* And it retains the information that it points to N elements.

I (manually) verified that the generated code is as efficient as using
plain raw pointers.
Allow to reset the MSX also after removal of cartridge/extension.Note that the reset is also performed when the insertion fails. That was
already the case before this patch. Maybe not too important.

The patch renames the also persistent variable for the checkbox. I don’t think
this is an issue in practice.

Closes #1814.
Implemented Yamanooto mapperThanks to Marcos Daniel Blanco Oliveira for the initial request and for
performing various tests on the real hardware.

This seems to work well, but more tests won’t hurt.

Two known missing features are:
* SCC stereo mode is not emulated.
* The HOME/DEL boot keys are not emulated. It’s not clear how the real
hardware intercepts these (it’s likely not via software??).
Forgot to adjust the windows build files
Added Yamanooto extension.Based on the mapper type as recently added by Wouter.
Yamanooto fix: config regs are NOT mirroredBut the mapper itself is.
Yamanooto: increase PSG volume
Reset mapper type when selecting a new ROM file.Closes #1813.
Only change the MSX mouse cursor when in the right phase to avoid trackball confusion. (#1816)
Add libglew-dev to the example list of packages.It was one of the few missing ones.
Fix for issue #1756: Menu bar doesn’t (reliably) appear on full screen in Windows, in contrast to Linux

Do not use SDL_SetRelativeMouseMode which is meant to pin the absolute mouse, causing the menubar to be unreachable in Windows.
It seems the pinning is done differently or not at all in Linux, hence not showing the issue.
The alternative SDL_SetWindowGrab does not pin the mouse, so that one is now used.
However this causes the cessation of mouse events when reaching the edges, which is why pinning was used in the pinning method.
To fix that issue with this non-pinning method, the mouse is now warped away from the edges when it is near one.

Originaly it was thought that we could simply do without grabbing the mouse, but that caused issues with multiple monitors,
or with explicitly enabling the grab option in windowed mode.
Merge branch ‘balyuf-balyuf_menubar’
Small tweak on 9e908f7 (no functional changes)
Yamnooto: add support to read segment number in debuggerFor now only the lower 8 bits (the full segment number is 10-bits). Will
try to extend this later (the current mechanism uses the ‘Debuggable’
interface, and that one is heavily byte-oriented).

Also removed some accidentally added debug code.
KonamiUltimateCollection: add support to read segment number in debuggerAlso limited to lower 8 bits, for now(?).
Extend segment number debug view to larger than 8-bitOnly in the ImGuiDebugger, the Tcl interface (via the “romblocks”
debuggable) is still limited to 8 bit.

Only the Yamanooto and the KonamiUltimateCollection mappers are extended
to actually provide more than 8-bit segment numbers. Are there other
mappers that have larger segment numbers?
Added ‘debug breakpoint ‘As a replacement for:
debug list_bp
debug set_bp
debug remove_bp
(These commands are still supported for backwards compatibility).

The new commands are:
debug breakpoint list (replacement for ‘debug list_bp’)
The return value has a different, more extensible, format.
debug breakpoint create (replacement for ‘debug set_bp’)
Instead of listing ‘address’, ‘condition’, ‘command’ and ‘-once’ in
a fixed order. They can all individually be specified like
debug breakpoint create -address 0x123 -command “myCommand” …
debug breakpoint configure (there was no existing equivalent)
This allows to change the properties of an existing breakpoint.
(No longer needed to delete and recreate.)
debug breakpoint remove (replacement for ‘debug remove_bp’)

See help-text in the commit for a more detailed description.

The motivation for this change is:
#1806
Make it possible to enable/disable breakpoints from Tcl

Currently the ImGuiBreakpoint window keeps a lot of state outside of
the openMSX core. E.g.
* It keeps track of disabled breakpoints (those don’t exist in the
openMSX core). In the future I’d like to add a ‘-disabled’ property in
the openMSX core breakpoints.
* It keeps track of the formatting of the address. E.g. ‘0x005f’ vs ’95’
vs ‘CHMOD’. In the future I’d like to move this functionality to
the core openMSX breakpoints.
* It keeps track of the sort-order.
* …
In other words: the idea is to move most (all) functionality to openMSX
core and make the ImGui window a dumb stateless viewer window.

This patch changes breakpoints, but we should do the same for
watchpoints and conditionals.
[1/2] refactor WatchIORemove ‘motherBoard’ member variable. Instead pass it as a parameter to
the methods that need it.

This is a preparation to be able to change the properties of an existing
WatchPoint (without having to delete the object and create another one).
For this we need to be able to unregister and then re-register.
[2/2] merge WatchIO into WatchPointWe want to be able to change the properties of a WatchPoint without
having to delete and re-create the object, including the type of the
watchpoint ({read,write}-{memory,IO}). For that to be possible we need
the same class to represent all these types.

Before this patch IO-watchpoints were represented via WatchIO and
memory-watchpoints via WatchPoint (which is a baseclass of WatchIO).
This class merges both into a single class.
Added ‘debug watchpoint […]’Similar to ‘debug breakpoint ‘ which we added in one of the
previous commits.
Added ‘debug condition ‘Similar to the corresponding ‘breakpoint’ and ‘watchpoint’ debug
subcommands.
Don’t keep list of breakpoints in sorted orderBefore this patch we kept the list of breakpoints sorted on address.
That allowed to use binary search to see if the current-pc is hit by a
breakpoint. With this patch that becomes a linear search.

This may seem like a performance degradation, and when there are many
breakpoints (+10(?), or +20(?), I didn’t actually measure) it indeed
will be slower. Though typically there won’t be that many breakpoints,
and then a linear search will be just as fast (or even faster if there
are only a few). Note that the most important (and most common) case of
no breakpoints at all is already taking a different code path (and there
we don’t do any breakpoint-check at all in the inner loop).

If performance ever does become an issue (in case of many breakpoints)
then we can still optimize it via a std::bitset. Then the check will be
very fast, and independent of the number of breakpoints (O(1)).

But the motivation for this change is not related to performance at all.
Instead, in some later commit, we want the GUI to use the openMSX
breakpoint list directly. And then we want to be able to reorder the
list to (re-)sort the table.
Move ‘prefix’ into BreakPoint, WatchPoint, DebugConditionWe had a lot of places in the code that duplicated the knowledge of how
to represent a breakpoint (or watchpoint or debug-condition) ID. So
stuff like:
strCat(“bp#”, bp.getId());
This patch replaces that with a new getIdStr() method.

Detail: some code used strCat() (resulting in a std::string), most code
used tmpStrCat() (resulting in a TemporaryString). In general the latter
can be more efficient because it (more often) avoids temporary memory
allocation. Though in this specific case the resulting strings are small
enough so that (usually) also std::string can avoid the allocation.
Keep formatting of {Break,Watch}Point addressBefore this patch the (begin or end) address of a breakpoint/watchpoint
was stored as an integer. And then e.g. for the list command we would
format it as a 4-digit hex number. In the GUI we would already
separately keep track of the original address string as entered by the
user. This patch now also stores the original string in the breakpoint
object itself (and then later patches will remove it from the GUI side).

To convert the string to a number we evaluate it as a Tcl expression.
That means that symbols are supported via the syntax:
$sym(mySymbolName)
Via the GUI we still allow the simplified syntax of using plain symbol
names. But internally that is then transformed into the above Tcl
expression.

Note that for performance reasons those Tcl expressions are not
constantly being re-evaluated. E.g. an expression like ‘[reg HL]’ to set
a breakpoint on the address where the HL register points to will not
automatically move the breakpoint whenever the HL register changes. It
is _intentionally_ left unspecified when the expressions are being
re-evaluated.
Add -enabled property to breakpoints/watchpoints/debug-conditions(Part of) the original goal of this patch series was to being able to
set disabled breakpoints from withing a Tcl script:
#1806
This commit adds such the property ‘-enabled’. And that allows to do
things like:
debug breakpoint create -address 0x123 -enabled false
debug watchpoint configure wp#10 -enabled true

This commit only adds the property in the openMSX core. The GUI doesn’t
use it yet.
Use -enabled property on the GUI sideThe previous patch introduced the ‘-enabled’ property on breakpoints,
watchpoints and debug-conditions. This patch uses that on the GUI side.

More in detail: before this patch in the openMSX core there only existed
enabled breakpoints (and watchpoints etc). On the GUI side it was useful
to be able to temporarily disable a breakpoint. This was done by
removing it from openMSX and then later, when it’s enabled again,
re-adding it. And this was one of the main reasons why the GUI kept it’s
own list of breakpoints (largely duplicate from the list in openMSX).
Disabled items in the GUI-list were indicated with a negative ID, items
that also exist on the openMSX side had a positive ID.

This patch removes the concept of ‘negative IDs’. Now all elements
on the GUI side always also exist on the openMSX side. For now the list
still exists on the GUI side (and we have code to keep both in sync).
But later patches in this series will fully remove the GUI list.
disassembly view: work on openMSX core breakpoints rather than gui-breakpoints

Next to the main ImGui ‘Breakpoints’ window, also the ‘Disassembly’
window operates on breakpoints. Before this worked with GUI-breakpoints,
e.g. because it also needed to work on disabled breakpoints. But since
the last few commits this is no longer needed. And now the disassembly
view directly works with core openMSX breakpoints.
ImGuiBreakPoints: remove commented out load/save codeAt some point in the past, when you exited and then restarted openMSX,
it would restore your breakpoints, watchpoints and debug-conditions.
Though doing that by default was a bad idea, and the feature was
disabled.

It may be a good idea to re-introduce this feature in the future, but
then as an optional feature, and part of a larger session management
feature. For that reason we didn’t fully remove the feature from the
code, but only commented it out.

But the previous/next commits in this series totally change the format
and the location of this information (e.g. moved from GUI to core
openMSX). So there’s not much point in keeping the old commented out
code. This patch removes it.
Remove state from ImGuiBreakPointsAll previous commits in this series were largly preparations for this
commit. This commit fully removes all state from ImGuiBreakPoints (well,
the only remaining state is whether the window is visible or not).

This allows to remove a lot of code: all code that was responsible for
keeping the state in sync between openMSX core and the GUI.

This is still a rather large patch, I couldn’t find an easy way to split
it into smaller chunks.

This basically finishes issue 1806:
#1806
the remaining commits in this series still make some cleanups.
Remove all but default constructors for BreakPoint/WatchPoint/DebugCondition

Instead we now default-construct the object and then call one or more
setXXX() methods.
Move ID-stuff from BreakPoint/WatchPoint/DebugCondition to BreakPointBase

The implementation was identical for all three subclasses. The main
reason it wasn’t moved before was because of a static counter ‘lastId’
in all subclasses. And this needs to be a separate counter for all
classes (moving it to the base class would make it a shared counter).

The ‘solution’ is to turn the base class into a CRTP class. That way
it’s a template with 3 separate instantiations, thus also separate
counters.

This became possible after earlier changes in this series: we no longer
need a common (non-templatized) base class.

And also for ProbeBreakPoint … that also allowed to do the
prefix-stuff from an earlier patch in this series.
wip: better error checking on create/configure subcommands
ImGuiBreakPoints: improve tooltipsE.g. with error messages for invalid: address, condition, command.
ImGuiBreakPoints: added hidden-by-default ‘once’ columnNow all breakpoint/watchpoint/debug-condition Tcl command line
functionality is also exposed in the GUI.
Fix various compiler warnings (mostly clang)
Fix msvc build files
ImGuiConsole: add extra spacing at the bottomBefore this patch, when the last output line contained an underscore
character ‘_’, it wasn’t visible. This patch corrects that.
Update ‘Dear ImGui’ from ‘v.1.915 WIP’ to ‘1.91.6 (Dec 11)’
ImGuiConsole: workaround missing callback on ESCWhen typing in the openMSX console, pressing ESC clears the current
line. Though because of some (to me) unexpected behavior in Dear ImGui
InputText() callback handling, we didn’t properly account for this
change. This commit adds a workaround.
ImGuiConsole: allow to cancel multi-line command with ESCTcl commands can span multiple lines. E.g. when a line has unbalanced
opening curly braces we need extra lines to obtain a full Tcl command.
More technically we use ‘Tcl_CommandComplete()’ to check if a command is
complete or whether we need extra lines. Visually the console prompt
changes from “>” to “|” to indicate we expect the continuation of the
previous line, rather than a new command line.

Usually this works fine. And it’s similar to how other shells (e.g.
bash) handle this. Though if you made a typo, and accidentally typed an
incomplete command (e.g. unbalanced braces or quotes) then it’s not so
easy to get back into the ‘normal’ state again.

E.g. in ‘bash’ you can cancel a multi-line input via ‘CTRL-C’. And
before we migrated the console to ImGui this also worked in openMSX.
Though in ImGui ‘CTRL-C’ is already used for “copy”. Instead we use ESC
to clear the current line. This commit extends that to also cancel an
in-progress multi-line command.
Per-channel balance other than {-100,0,+100}, use in YamanootoWe could already specify the balance for individual channels. E.g. the
Pioneer PX-7 machine set the PSG channels:
channel 1: center
channel 2: left
channel 3: right
This was done via a section in the config file:


0
-100
100

Before this patch the value for the balance setting was only allowed to
be:
-100: fully left
0: center
100: fully right
This patch generalizes that to all values between -100 and 100.

This patch also uses that feature for the Yamanooto SCC device. Though
instead of via the config file, it sets per-channel balance settings
directly from the C++ code:
channel 1: 50% left, 50% right (values specified in the Yamanooto manual)
channel 2: 66% left, 33% right
channel 3: 33% left, 66% right
channel 4: 66% left, 33% right
channel 5: 33% left, 66% right
Though I have to admt that personally I don’t really notice this pseudo
stereo effect when playing Konami games. In my tests I had to use more
extreme values (like 20%/80%) to verify that the implementation was
actually working as intended.
ImGuiDebugger: allow to open multiple disassembly viewsThis can be useful if you want to see multiple assembly routines at the
same time (e.g. to compare them).

By default the first view will scroll to the PC on break. All other
views will not (by default). But this behavior is now configurable
(right click context menu).

When selecting ‘Show in disassembly’ in the breakpoints or symbols
window, this only has effect on the first disassembly view.
ImGuiPalette: use MSX1 palette on MSX1 machines#1748
On MSX1 VDP’s the sprite and tile viewer should show colors matching that VDP’s colors

In the pallette viewer, both “VDP palette” and “Fixed palette” now use
the MSX1 colors. “Custom palette” still uses the MSX2 RGB777 based
palette.

The selected palette is used in the bitmap/tile/sprite-viewer.
Fix typo in assert (introduced in 6f8546b)
Fix T9769 sub type for this machine.
ImGuiBreakPoints: also recognize ‘$::sym(name)’So both:
$sym(name)
$::sym(name)

In a Tcl proc the extra ‘::’ are needed to refer to the global variable
‘sym’ (rather than a local variable in the proc). But the breakpoint
address expression is always evaluated in the global context, so there
the extra ‘::’ is not needed. It is allowed, and for consistency I can
see why you’d want to write it like that. So now the GUI recognized both
formats.

Note: this is not related to evaluating the expression, it’s purely the
representation in the GUI: the GUI recognizes some specific Tcl
expression patterns and then replaces those with a simpler notation. And
similarly if you type that simpler notation in the GUI, it’s internally
replaced with the full Tcl expression.
Removed OSD raster-viewA different (better) version is now available in the ImGui bitmap
viewer.

I only noticed this now: this old version showed the ‘wrong’
Y-coordinate. Or at least, for the X-coordinate it converted absolute
VDP numbers into MSX-coordinates, thus taking the border and set-adjust
into account. But for the Y-coordinate it just showed absolute VDP
numbers. The ImGui raster view also shows MSX lines numbers, so lines in
the top border have a negative value.
Removed ‘toggle_fps’ OSD indicatorThe replacement is the ‘fps’ field in the ImGui status bar.

Manuel remarked that the OSD fps is only a small rectangle, while the
status bar contains much more information. That’s true.

However currently the old OSD fps indicator is placed in the top-left
corner _behind_ the main menu bar. Making it practically useless. We
could of course fix that, but I think we’d better spend that effort in
making the status bar more configurable. E.g. replace the current “Main
menu > Misc > Show status bar” checkbox with a sub-menu containing
checkboxes for all the individual elements (and maybe still one global
enable checkbox).
Removed OSD info panelReplaced by ImGui status bar.

It does not 100% show the same information. Some more, some less. Some
only by hovering over an item. All important info is there (IMHO).

We could still improve the ImGui status bar. See also previous commit
message.

Atualizações:

Destacar símbolos conhecidos na visualização de memória em formato hexadecimal.
Adicionada a compatibilidade para carregar arquivos de símbolos gerados pelo WLA-DX.
Adicionados testes unitários para verificar a importação de símbolos do WLA-DX.
Corrigido um erro no unittest para símbolos do WLA e levemente modificado o processo de detecção do formato.
#1747 Adicionada a compatibilidade com o arquivo MAP gerado pelo Z80ASM do Z88DK.
Issue #1754 Emulação incorreta do acesso à VRAM com a tela desativada no MSX2.
TODO: ainda precisa de testes.

Limitar as mensagens do ImGui: Quando um script Tcl está gerando avisos a uma taxa muito alta, a interface gráfica pode se tornar inutilizável. Às vezes, a única forma de recuperar seria matar o openMSX. Por exemplo: debug set_bp 0x38 bla
(“bla” é uma expressão Tcl inválida e é avaliada a cada IRQ, 50 vezes por segundo).
Nesta correção, limitamos a quantidade de mensagens exibidas caso o número de mensagens seja muito grande em um curto espaço de tempo. No momento, os critérios definidos são:

Mais de 5 mensagens dentro de um segundo.
Ou mais de 10 mensagens dentro de um minuto.
Todas as últimas mensagens ainda serão exibidas, mas durante o limite, a janela de mensagens não será realçada nem mostrará popups modais.

Este patch é apenas uma prova de conceito e os detalhes de como a limitação será ajustada podem ser aprimorados.

Adicionar menu de contexto com a opção ‘Mostrar na Desmontagem’ para endereços na janela de breakpoints.
Mesclar o branch ‘zappatic-breakpoint-jump-to-disassembly’.
Corrigir: a janela de demonstração do imgui desaparece junto com a barra de menu principal. Testamos de forma indireta se a barra de menu estava sendo exibida, mas isso dependia de um detalhe de implementação. Agora verificamos diretamente as coordenadas do mouse, o que pode corrigir problemas de tela cheia no Windows.
Como bônus, essa abordagem permite que a barra de menu seja totalmente ocultada. Antes, ela só desaparecia até um valor alpha de 0.001, o que era tecnicamente invisível, mas ainda assim desenhado.

Cassetteplayer: adicionada a subcomando ‘setpos’.
TODO: tornar essa funcionalidade disponível na interface gráfica.
Permite chamar ‘cassetteplayer setpos’ via GUI.
Adicionada tooltip para o indicador de posição da fita (também agora editável).
Fechamento de problemas:

#1725 (Juntamente com 9791f02 e 95d6b54).

Adicionar pergunta sobre duas barras LED/icon e corrigir nível de altura.

Atualizar SDL2 para a versão 2.30.7.

Atualizar Tcl para 8.6.15.

Atualizar libPNG para 1.6.44.

Exibir informações extras no visualizador de tiles:

Solicitação via issue #1759: Informações faltando no novo visualizador de tiles comparado ao antigo depurador.
Atualizar FreeType para 2.13.3:

Para compilar no Windows, é necessário adicionar o rasterizador SVG.
Não quero investigar o motivo.
Editor depurável: corrigir falha ao clicar na lista de dropdown do tipo de dado (no painel de visualização de dados).

Abreviar ‘channel’ para ‘ch.’ para economizar espaço.

Fechar problemas:

#1729: Não persistir a configuração freq_lock.
Outros detalhes:

Executar auto-run no rewind em vez de reinserir a fita. Isso garante que, ao reiniciar, a fita não será reinserida, o que tornaria impossível resetar e continuar carregando o próximo item da fita. Isso se alinha mais com o comportamento real de um MSX.
Correção de Bugs:

#1724: Corrigido o problema mencionado.

Atualizar Dear ImGui para v1.19.3 (de v1.91.0).

Permitir configurações de velocidade menores que 1 (valor flutuante).

Corrigir aviso de (tempo de execução) sobre IDs duplicados.

Mais Correções:

Adicionar motor de controle à janela do deck da fita:
Consultar o status atual diretamente do CassettePlayer.
Também usamos o CassettePlayer diretamente para consultas na janela de Deck da Fita e no menu de Mídia, tornando mais eficiente.
Fechar #1734.

Mesclar o branch ‘MBilderbeek-master’.

Issue#1780: Botões da barra de ferramentas com tamanhos e formas inconsistentes.

Os ícones usados são realmente glifos em uma fonte personalizada e esses glifos têm tamanhos ligeiramente diferentes. Encontramos uma solução temporária para corrigir isso, esticando todos os ícones para o mesmo tamanho comum.
HQCommon: Preparação para tamanhos diferentes de 320.

Otimizações de Escala:

HQCommon: otimizar as posições do deslocamento RGB para melhorar o desempenho do “hq scaler”.
Refatoração do gl::PixelBuffer:

Substituído ‘largura/altura’ por ‘tamanho’ para um buffer mais eficiente.
Corrigir a exclusão de “savestates” (estados de salvamento). Isso foi quebrado após o commit 078e8f5 (ups).

[1/11] Listar os estados de salvamento disponíveis apenas com código C++, como ocorre com as reproduções. Preparação para facilitar a exibição de mais informações sobre os estados no menu.

Além disso: definir a extensão do arquivo de “savestate” e a pasta em um único lugar, pelo menos dentro deste arquivo. (Não há um lugar óbvio no nosso código não-GUI para colocar isso…)

Essa mudança também altera o comportamento: se não houver estados de salvamento, o item do menu não ficará mais desabilitado. Em um commit futuro, restauraremos algo semelhante, mas mais fácil de entender: diremos explicitamente que nenhum estado foi encontrado.

[2/11] Não recriar a lista de “savestates” / “replays” a cada quadro. Em vez disso, armazene-a em cache até o menu ser reaberto.
[3/11] Mostrar no menu que não há estados ou reproduções, se for o caso. Corrige a regressão que fazia o menu aparecer vazio, em vez de desabilitar o item do menu. Agora fica mais claro o que está acontecendo.
[4/11] Mostrar os estados de salvamento ordenados por tempo, do mais recente para o mais antigo.
[5/11] Mostrar as reproduções ordenadas por tempo, do mais recente para o mais antigo.
[6/11] Usar uma tabela em vez de uma lista para reproduções para mostrar o tempo.
[7/11] Exibir a data/hora no submenu de “load savestate” (carregar estado de salvamento). A duplicação será resolvida em um commit futuro.
[8/11] Remover a maior parte da duplicação entre “loadstate” e “loadreplay”.

Usando a mesma estrutura para ambos
Fatorando as flags da tabela de seleção
Fatorando a maneira de configurar e ordenar as colunas
A formatação da data/hora já foi fatorada.
[9/11] Tornar as tabelas “loadstate” / “loadreplay” mais estreitas. Elas estavam muito largas.
Feito mostrando apenas a data ou apenas a hora (quando for hoje). A data/hora completa é exibida em uma dica de ferramenta. Também foi feita uma dica de ferramenta com o nome completo, para que possamos tornar a coluna de nomes mais estreita sem nos preocuparmos com nomes longos não sendo legíveis.
Para evitar cálculos duplos com as funções de data/hora, já convertemos para “std::time” ao escanear os arquivos.
[10/11] Ajustar alguns textos em relação à visualização prévia.

Mostrar “Nenhuma visualização disponível…” se for o caso
Não adicionar textos desnecessários acima da lista e da visualização quando disponíveis
[11/11] Fatorar mais código comum entre “loadstate” / “loadreplay”.
Atualizar “Dear ImGui” de ‘v1.91.3’ para ‘v1.91.5 WIP (28 de outubro)’
Aplicar várias sugestões (menores) do SonarCloud
Aplicar várias sugestões (menores) do SonarCloud
SonarCloud: tornar operadores sobrecarregados “amigos ocultos”. Veja aqui o porquê isso é melhor:
https://rules.sonarsource.com/cpp/RSPEC-2807/
Reversão parcial do commit anterior (solução alternativa para gcc). O código estava correto, funcionava com clang, msvc e gcc-13. Mas não com gcc-11 e gcc-12.
Remover o algoritmo ‘hqlite’ do redimensionamento.
Ele foi adicionado como uma versão mais leve do algoritmo ‘hq’ (em vez de verificar se as cores são semelhantes, verifica se as cores são iguais). Há 20 anos isso era importante, mas hoje em dia não tanto. Ou melhor, a qualidade extra é mais importante do que a velocidade.
A principal motivação para remover ‘hqlite’ é simplificar nosso código base (um pouco).
Remover o redimensionador ‘fast’
Rápido, mas de baixa qualidade (pode causar efeitos horríveis de aliasing). Mas, com os computadores atuais, não há razão para ainda usar o redimensionador de baixa qualidade.
A principal motivação para removê-lo também é simplificar nossa base de código (um pouco).

Este membro de tamanho permite adicionar (opcionalmente) verificação de limites no MemBuffer.

Ele também permite (corretamente) converter o MemBuffer em um std::span, o que também facilita a verificação de limites e de estouros de buffer.

Mais detalhes: Esta atualização estende o MemBuffer com estes métodos convenientes:

size() e empty()
begin() e end()
front() e back()
operator[] com (opcional) verificação de limites
Conversão para span, first(), subspan()
Isso aproxima o MemBuffer de um std::vector. As diferenças remanescentes são:

std::vector ainda é mais pesado. Normalmente, sizeof(vector) é 24, e sizeof(MemBuffer) é 16.
O MemBuffer mantém o conteúdo inicial não inicializado. O std::vector sempre inicializa, mesmo que o buffer seja imediatamente sobrescrito (por exemplo, ao ler de um arquivo).
Por causa disso, é permitido usar o MemBuffer apenas com tipos que sejam trivialmente copiáveis (a cópia é equivalente a memcpy). Esta atualização adiciona tal verificação.
Na destruição, o MemBuffer apenas libera o bloco de memória. O std::vector destrói adequadamente todos os elementos que contém. Mas é possível que o destruidor desses elementos seja trivial (não faça nada), e, nesse caso, o std::vector também não precise fazer nada extra.
Por isso, o MemBuffer só pode ser usado com tipos trivialmente destrutíveis. Esta atualização também adiciona uma verificação para isso.
Portanto, as diferenças remanescentes são suficientes para justificar a existência do MemBuffer (não podemos simplesmente substituí-lo por um std::vector e manter o mesmo desempenho).

Essa mudança no MemBuffer permite várias simplificações. Mas isso ficará para patches subsequentes:

Simplificar o uso do MemBuffer em ReverseManager e OutputBuffer.
Simplificar o uso do MemBuffer em SettingsConfig, XMLDocument.
Simplificar o uso do MemBuffer em Debugger, MSXtar, RamDSKDiskImage.
Simplificar o uso do MemBuffer em CompressedFileAdapter, ZlibInflate, FileBase.
Simplificar o uso do MemBuffer em FilePoolCore.
Simplificar o uso do MemBuffer em Ram.
Simplificar o uso do MemBuffer em Rom.
Simplificar o uso do MemBuffer em ResampleHQ.
Simplificar o uso do MemBuffer em SDLSoundDriver.
Simplificar o uso do MemBuffer em WavData.
Simplificar o uso do MemBuffer em Base64, HexDump.
Simplificar o uso do MemBuffer em DeltaBlock, TigerTree.
Simplificar o uso do MemBuffer em PixelBuffer.
Simplificar o uso do MemBuffer em RawFrame.
Simplificar o uso do MemBuffer em ZMBVEncoder, V9990CmdEngine.
Outras mudanças e correções:

Correção na exibição do valor de coordenadas no visualizador de bitmap.
Aplicação de sugestões do clang-tidy para modernização do código, como a substituição de std::min() aninhado por uma lista de inicialização.
Refatoração de interações entre rapidsax e XMLElementTriggered. O código foi ajustado para melhorar o uso de std::string_view, garantindo que ele seja corretamente tratado como uma string terminada em zero quando necessário.
Adição de verificações de std::optional. Assegura que o acesso a valores em std::optional seja feito de forma segura.
Correções de compilador relacionadas ao clang. Essas correções envolvem ajustes para melhorar a compatibilidade e evitar erros de compilação com versões mais recentes do clang.
Refatoração de código para otimizar a leitura e escrita de memória (como no caso do YMF278B e a memória de flash no dispositivo DalSoRiR2).
Correção de um bug relacionado ao uso do mouse em telas de várias monitoras no Windows, resolvendo problemas de acesso ao menu e interação com o mouse em telas cheias.
Os novos comandos são:

debug breakpoint list (substituição para ‘debug list_bp’): O valor retornado tem um formato diferente e mais extensível.
debug breakpoint create (substituição para ‘debug set_bp’): Ao invés de listar ‘endereço’, ‘condição’, ‘comando’ e ‘-once’ em uma ordem fixa, agora podem ser especificados individualmente, como:
debug breakpoint create -address 0x123 -command “meuComando” …
debug breakpoint configure (não havia equivalente anterior): Isso permite alterar as propriedades de um breakpoint existente, sem a necessidade de deletá-lo e recriá-lo.
debug breakpoint remove (substituição para ‘debug remove_bp’).
Veja o texto de ajuda no commit para uma descrição mais detalhada.

Motivação para essa mudança: #1806
Tornar possível habilitar/desabilitar breakpoints de dentro de um script Tcl.

Atualmente, a janela de breakpoints do ImGui mantém muitos estados fora do núcleo do openMSX. Por exemplo:

Ela mantém o controle de breakpoints desabilitados (esses não existem no núcleo do openMSX). No futuro, gostaria de adicionar uma propriedade ‘-disabled’ nos breakpoints do núcleo do openMSX.
Ela mantém o controle da formatação do endereço, como ‘0x005f’ vs ’95’ vs ‘CHMOD’. No futuro, gostaria de mover essa funcionalidade para os breakpoints do núcleo do openMSX.
Ela mantém o controle da ordem de classificação.

Ou seja, a ideia é mover a maior parte (ou toda) a funcionalidade para o núcleo do openMSX e tornar a janela do ImGui um visualizador sem estado.

Este patch altera os breakpoints, mas devemos fazer o mesmo para watchpoints e condicionais.

[1/2] Refatorar a variável membro ‘motherBoard’ de WatchIORemove. Agora ela é passada como parâmetro para os métodos que precisam dela.

Isso é uma preparação para permitir a alteração das propriedades de um WatchPoint existente (sem precisar deletar e recriar o objeto). Para que isso seja possível, precisamos ser capazes de cancelar o registro e registrá-lo novamente.

[2/2] Mesclar WatchIO em WatchPoint. Queremos poder alterar as propriedades de um WatchPoint sem precisar deletar e recriar o objeto, incluindo o tipo do watchpoint (leitura/gravação de memória/IO). Para isso, precisávamos que a mesma classe representasse todos esses tipos.

Antes desse patch, watchpoints de IO eram representados por WatchIO e watchpoints de memória por WatchPoint (que é uma classe base de WatchIO). Este patch une ambos em uma única classe.

Adicionado:

debug watchpoint […]
Semelhante ao debug breakpoint que foi adicionado em um dos commits anteriores.
debug condition
Semelhante aos subcomandos correspondentes de ‘breakpoint’ e ‘watchpoint’.
Não manter a lista de breakpoints em ordem classificada: Antes desse patch, mantínhamos a lista de breakpoints ordenada por endereço. Isso permitia usar uma busca binária para verificar se o endereço atual foi atingido por um breakpoint. Com este patch, a busca passa a ser linear.

Isso pode parecer uma degradação de desempenho e, de fato, será mais lento quando houver muitos breakpoints (+10 ou +20, por exemplo). No entanto, normalmente não haverá tantos breakpoints, e uma busca linear será tão rápida (ou até mais rápida se houver poucos). Note que o caso mais importante (e mais comum), sem breakpoints, já segue um caminho de código diferente, onde não há verificação de breakpoints no loop interno.

Se o desempenho se tornar um problema (em caso de muitos breakpoints), podemos otimizar isso usando um std::bitset, tornando a verificação muito mais rápida e independente do número de breakpoints (O(1)).

Mas a motivação para essa mudança não está relacionada ao desempenho, mas sim para que em um commit futuro possamos fazer a GUI usar diretamente a lista de breakpoints do openMSX, permitindo reordenar a lista para (re)classificar a tabela.

Mover ‘prefix’ para BreakPoint, WatchPoint, DebugCondition: Havia muitos lugares no código que duplicavam o conhecimento sobre como representar um breakpoint (ou watchpoint ou debug-condition). Agora, isso foi substituído por um novo método getIdStr().

Detalhe: algum código usava strCat() (resultando em um std::string), enquanto a maioria usava tmpStrCat() (resultando em um TemporaryString). O último pode ser mais eficiente porque evita a alocação temporária de memória. Porém, neste caso específico, as strings resultantes são pequenas o suficiente para que o std::string também consiga evitar a alocação.

Manter o formato de endereço de BreakPoint/WatchPoint: Antes desse patch, o endereço de início ou fim de um breakpoint/watchpoint era armazenado como um número inteiro. E depois, por exemplo, no comando de lista, ele era formatado como um número hexadecimal de 4 dígitos. Na GUI, já mantínhamos separadamente a string original do endereço, como inserida pelo usuário. Este patch agora também armazena a string original no objeto do breakpoint (e patches posteriores irão remover isso da parte da GUI).

Adicionar propriedade -enabled a breakpoints/watchpoints/debug-conditions: Parte do objetivo original dessa série de patches era permitir a definição de breakpoints desabilitados a partir de um script Tcl. Este patch adiciona a propriedade ‘-enabled’, permitindo fazer coisas como:

debug breakpoint create -address 0x123 -enabled false
debug watchpoint configure wp#10 -enabled true
Este patch adiciona a propriedade no núcleo do openMSX, mas a GUI ainda não a utiliza.

Usar a propriedade -enabled na GUI: O patch anterior introduziu a propriedade ‘-enabled’ nos breakpoints, watchpoints e debug-conditions. Este patch agora a usa na GUI.

Mais detalhadamente: antes, no núcleo do openMSX, existiam apenas breakpoints (e watchpoints etc.) habilitados. Na GUI, era útil poder desabilitar temporariamente um breakpoint. Isso era feito removendo-o do openMSX e, depois, quando habilitado novamente, re-adicionando-o. Isso era uma das principais razões pelas quais a GUI mantinha sua própria lista de breakpoints (em grande parte duplicada da lista no openMSX).

Este patch remove o conceito de “IDs negativos”. Agora todos os elementos na GUI existem também no lado do openMSX. Para agora, a lista ainda existe na GUI (e temos código para manter ambas as listas sincronizadas). Mas patches posteriores dessa série irão remover completamente a lista da GUI.

Visão de desassemblagem: trabalhar com breakpoints do núcleo openMSX em vez de breakpoints da GUI: Além da janela principal do ImGui ‘Breakpoints’, a janela ‘Disassembly’ também operava com breakpoints. Antes, isso funcionava com breakpoints da GUI, já que também precisava lidar com breakpoints desabilitados. Mas desde os últimos commits, isso não é mais necessário. Agora, a visão de desassemblagem trabalha diretamente com breakpoints do núcleo openMSX.

ImGuiBreakPoints: remover código comentado de load/save: Em algum momento no passado, ao sair e reiniciar o openMSX, ele restaurava seus breakpoints, watchpoints e debug-conditions. Porém, restaurar isso por padrão era uma má ideia, então esse recurso foi desabilitado.

Agora, os commits subsequentes mudaram o formato e o local dessa informação (de GUI para o núcleo do openMSX). Por isso, não faz sentido manter o código antigo comentado, e este patch o remove.

Remover estado do ImGuiBreakPoints: Todos os commits anteriores dessa série foram em grande parte preparações para este. Este patch remove totalmente o estado de ImGuiBreakPoints (exceto o estado de visibilidade da janela).

Isso permite remover muito código: todo código responsável por manter o estado sincronizado entre o núcleo do openMSX e a GUI.

Este é um patch grande, pois não consegui encontrar uma maneira fácil de dividi-lo em partes menores.

Isso basicamente finaliza a questão #1806.

Os commits restantes dessa série fazem alguns ajustes finais.