# Nuance 0.6.7

A NUON (VM Labs) emulator for Windows and Linux.

Copyright 2002 - 2007 Mike Perry and 2020 - 2026 all the open source contributors (see separate license.txt)

Continued using the released source/docs in honour of the original author by Carsten Waechter (toxie at ainc.de) in 2020.
Linux/libretro port by WizzardSK in 2026.

NUON is/was a trademark of Genesis Microchip, Inc.

## Disclaimer

This emulator was developed in a clean room setting, using only the Nuon SDK
architecture documentation, the llama assembler, vmdisasm disassembler, and
lots of hand crafted automation tools to help generate assembly files and
parse the output.  We cannot guarantee that this program will not blow up your
computer.  It is certainly capable of causing memory access violations.  If
you lose unsaved data while playing with it, don't say that we didn't warn you.

## Requirements

This emulator requires SSE2 instruction support, at least 200 Megabytes
of free RAM, and an OpenGL 1.5 implementation with support for GLSL,
so basically any halfway recent machine can run it.

The emulator is completely and utterly CPU bound.  Some machines
may even suffer reduced performance when
running the less demanding SDK demos, or may hang on certain game situations
(in the latter case try disabling AudioInterrupts in the `nuance.cfg`, at
the cost of missing or screwed up sound).

## Installation (Windows)

Extract the distribution files into a new directory, click on Nuance.exe and you're
good to go.  The bios.cof, minibios.cof and minibiosX.cof files contain Aries assembly
implementations of some BIOS routines and a complete miniBIOS.  These files must be
kept in the same directory as the main executable, plus all the GLSL shader files (.vs, .fs).

## Installation (Linux)

### 32-bit build

The original x86 JIT dynamic recompiler requires a 32-bit build.

```bash
sudo apt install gcc-multilib g++-multilib libgl1-mesa-dev:i386 libx11-dev:i386 libpulse0:i386
mkdir build32 && cd build32
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-m32" -DCMAKE_CXX_FLAGS="-m32" -DCMAKE_EXE_LINKER_FLAGS="-m32"
make -j$(nproc)
```

### 64-bit build

This one uses asmjit.

```bash
sudo apt install build-essential cmake libgl1-mesa-dev libx11-dev libsdl2-dev
mkdir build64 && cd build64
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
```

The bios.cof, minibios.cof, minibiosX.cof, nuance.cfg and GLSL shader files are
automatically copied to the build directory by CMake.

## Project structure

```
NuanceResurrection/
  src/           - All C/C++ source and header files
  external/      - Bundled libraries (GLEW, miniaudio, MurmurHash3)
  compat/        - Windows API compatibility headers for Linux builds
..thirdparty/    - Everything needed for .CHD support
  CMakeLists.txt - Build system
  *.cof, *.cfg   - BIOS and configuration files
  *.vs, *.fs     - GLSL shader files
```

## Usage (Linux)

The Linux version can load games directly from ISO, CHD or ZIP/RAR/7z files (plus executables and .CD packages):

```bash
./nuance /path/to/game.zip
./nuance /path/to/game.iso
./nuance /path/to/NUON/nuon.run
```

Audio output uses miniaudio (bundled) which auto-detects PulseAudio or ALSA.
Video uses X11/GLX with GLEW (bundled source).  ZIP/RAR/7z/ISO/CHD files are mounted
via FUSE (mount-zip/archivemount) for instant loading without extraction.

### Linux keyboard shortcuts

| Key | Function |
|-----|----------|
| F1 | Toggle fullscreen |
| F2 | Load game (native file dialog via kdialog/zenity) |
| F3 | Show status (MPE, comm bus, compiler stats) |
| F4 | Show MPE3 registers |
| F5 | Show kprintf log |
| F6 | Dump MPE memory to .bin files |
| F7 | Configure input (interactive key assignment) |
| F8 | Reset all MPEs |
| F9 | Pause / Resume emulation |
| F10 | Single step (execute one cycle on all MPEs) |
| F11 | Show disassembly of current packet |

The window title bar shows Kc/s (emulated kilocycles per second) and FPS in real time.

## Usage (Windows)

The Windows build can also load games directly from ISO, CHD and ZIP files
(no need to unpack these first):

```
Nuance.exe C:\path\to\game.zip
Nuance.exe C:\path\to\game.iso
Nuance.exe C:\path\to\NUON\nuon.run
```

You can also drag-and-drop a `.run` / `.cd` / `.cof` / `.nuon` / `.iso` / `.chd` / `.img` / `.zip`
onto either the control panel window, or the game window - it will go through the
same loader as the Load File button. The file dialog now filters by NUON-related
extensions by default.

ZIPs and ISOs/CHDs are handled by bundled libraries (miniz + libchdr + a built-in ISO9660 parser),
so there are no external runtime dependencies. ZIPs containing an inner ISO have
just the ISO extracted and read on the fly; ZIPs containing an extracted NUON
folder have all entries unpacked to a temp directory. RAR and 7z are not
supported on Windows - please extract those manually first.

Audio output uses miniaudio (bundled) which routes through WASAPI / DirectSound /
WinMM automatically.

## Configuration

The emulator uses configuration files for initializing options.  The configuration
file to use can be specified by passing in the file name as a parameter to the
emulator executable.  If no parameter is specified, the default filename `nuance.cfg`
is used.

Each configuration file must be updated to select an appropriate base path to be
used for loading files from DVD.  The entry should point to the directory
containing the nuon.run and nuon.dat files.  The DVDBase config entry is prepended
on to the file name parameters passed to MediaOpen and FileOpen.  The path names
should have a trailing backslash.  If you wish to run of the commercial games off
of an original DVD, set the DVDReadBase entry to `<DriveLetter>:\Nuon\` where
`<DriveLetter>` is the drive letter of the DVD drive.  Dynamic
recompilation may be configured similarly using an entry labeled "DynamicCompiler."
Additional settings for the dynamic compiler are discussed
in the Dynamic Compiler section of this document.

## Instructions

The emulator will display a control panel window where you can load a file, start
and stop individual processors and start and stop the emulation loop.

The LED indicators at the top left of the control panel show which processors are
currently running.  You can double click the LEDs to toggle the running state
of each processor.  This should only be done while the main emulator loop is
stopped.

Use the Load File button to load a COFF executable or NUONROM-DISK file (or
respective containers) into
memory.  If the load is successful, the emulation loop will automatically be
started as if the "Run" button were pressed.  Prior to starting the emulation
loop, the pcexec register of MPE3 will be set to the entry point of the
executable and the mpeGo bit of the mpectl register will be set.

Use either the "Run" or "Single Step" buttons to execute a sequence of code.
If the Single Step button is used, the emulator will attempt to execute a
single instruction on each of the four MPEs.  If an MPE does not have its mpeGo
bit set, no instruction will be executed on that MPE.  If the Run button is
used, the emulator will execute instructions on all of the MPEs until it
detects that all MPEs are halted.  Use the stop button to stop the emulator loop.
When the "Stop" button is used, the running state of each processor is not
modified, only the flag that enables the emulation loop to execute another
iteration.  Note that when the dynamic recompiler is enabled, the processors
may execute blocks of code consisting of multiple packets.  This will behave
as if each processor has a code-dependent system clock.  If synchronous operation
is required during debugging, use the single step mode.

Use the "Single Step" button to execute a single instruction on each processor
that is currently running.  The single step mode will work even if the dynamic
recompiler is enabled.  Prior to executing each instruction, the code cache of
compiled blocks is invalidated so that only a single packet will be interpreted.
This may cause a brief reduction in performance when the "Run" mode is re-entered
due to the fact that some blocks will need to be recompiled.

When using single step mode and when the emulator loop is stopped, the display
window in the center of the screen will be updated with a disassembly of the
next packet to be executed.  To change the MPE that is used for disassembly,
single click one of the MPE labels next to the MPE LED indicators.  Note that
the disassembly may not represent the original ordering of instructions within
the packet and that the disassembly shows the instructions in their canonical form.

One user breakpoint address may be specified using a text file named
`breakpoint.txt` located in the Nuance working directory.  If this text file
is present, the emulator will halt any MPE that attempts to execute an
instruction at that address.  This can be used to emulate a 'run to
breakpoint' mode.  To run a program without the breakpoint, simply set the
breakpoint address to 0.  The text file may contain multiple lines, but only
the first line is parsed.  The first line should contain a 32-bit hexidecimal
address, e.g. `20301ABC` followed by a carriage return.

There are two interlaced fields per frame.  A real NTSC Nuon-based player displays
at 60 fields per second.

Joystick emulation via keyboard is active only in the video display window.
The video display window may be resized to any desired size and the video
output will be stretched to fit.  To quit the application, stop the processor
emulation and then click the close button of the Control Panel window.

## Loading games

1. If you want to run one of the supported games from a DVD player,
   simply skip to step (3).  The emulator automatically sets the DVDBase variable to the
   directory containing the selected program.

2. If you want to run a supported game from some other media
   type, copy all files from the Nuon directory on the DVD to a directory on the
   media from which you wish to load the files.  Most games will only require the
   nuon.run and nuon.dat files found in the Nuon directory of the DVD.  Some games
   may have additional data files that are required, but if the nuon.run and nuon.dat
   files are not copied, you are doomed to certain failure.

   Easiest is to just use a container (.ISO,.CHD or .ZIP).

   An image file mounted in a virtual
   DVD device will also work but the image must be a complete DVD image.

3. Click the "Load File" button.

## Dynamic Compilation Options

Nuance is capable of re-compiling basic blocks of code (HLE), performing optimizations
on the code block and interpreting the optimized instruction sequence.  This allows
enhanced performance due to code optimization and reduction of dispatch loop overhead,
particularly where multiprocessor synchronization and interrupt processing is involved.

This section describes the configuration file entries that apply to the dynamic compiler.
For more information on the implementation details of the compiler, please read the
`DynamicCompiler.txt` file included in the distribution package.

The configuration entries applicable to dynamic compilation are:

- **`[DynamicCompiler]`** `Enabled`/`Disabled`: forces (slower) interpretation when disabled, recommended: `Enabled`

- **`[CompilerConstantPropagation]`** `Enabled`/`Disabled`: toggles constant propagation phase that is performed after fetching
  the block instructions. NOTE: Might still be a bit buggy in corner cases, but recommended: `Enabled`

- **`[CompilerDeadCodeElimination]`** `Enabled`/`Disabled`: toggles a dead code elimination phase that is performed after constant
  propagation. NOTE: Still buggy, recommended: `Disabled`

- **`[DumpCompiledBlocks]`** `Enabled`/`Disabled`: NOTE: This option is only available in custom builds, not released versions!
  Enabled/Disabled: toggles file dump of blocks that are compiled during execution.  When
  enabled, the emulator will print the resulting optimized blocks in a readable format to
  the files SuperBlocks0.txt through SuperBlocks3.txt corresponding to MPE0 through MPE3.
  Note that these files can grow in size very quickly.  It is not uncommon for the files to
  grow beyond 500 megabytes or even wrap around the maximum file size of 4 GB, recommended: `Disabled`

- **`[MPE3PacketHack]`** `Enabled`/`Disabled`: toggles a dynamic compiler hack that avoids e.g. a hang in T3K, recommended: `Enabled`
  (otherwise (Disabled), for T3K please use the recommendation in GameCompatibility.txt instead)
  (one can also choose `T3K` for the minimal subset needed to make T3Ks level select hang go away)

## Flash ROM Support

Nuance provides emulation support for the Atmel AT49BV162A/163A flash EEPROM chips.  These
chips provide 2MB of ROM space starting at address `$F0000000`.  The flash interface is compatible
with the VMLabs libflash library.  When the emulator is started, the virtual flash ROM will be
populated with data from the file `flashEEPROM.bin` if it exists.  When the emulator is exited,
the virtual flash ROM contents will be dumped back out to the `flashEEPROM.bin` file.

The virtual flash EEPROM memory range can be accessed via standard MEM unit load instructions.
The emulator cannot currently execute instructions out of ROM.  Please note that the ROM emulation
is not perfect and can cause corrupted bytes to be output in a repetitive fashion when running the
Samsung BIOS update program.

## printf Debugging (kprintf) Support

The Nuon rombios library implements a function `kprintf` which isn't included
in any of the SDK headers, but is defined as follows:

```c
extern void kprintf(const char *fmt, ...);
```

It behaves like one would expect printf to. Nuance implements this BIOS
function by storing the generated text in a ring buffer that can be viewed in
the status dialog by clicking the "kprintf Log" button. Additionally, Nuance
can log the kprintf output to a file. To enable logging, include the
`[DebugLogFile]` section in your nuance.cfg file, and include the filename (or
full path) of the desired log file on the next line, e.g.:

```
[DebugLogFile]
nuance_debug.log
```

Here's a small sample code listing demonstrating how to use the functionality
in a Nuon program:

```c
#include <nuon/bios.h>
extern void kprintf(const char *fmt, ...);

int main(void) {
    kprintf("Hello, world! %d %d %d\n", 1, 2, 3);
    return 0;
}
```

Compiling and running this program in Nuance will output:

```
Hello, world! 1 2 3
```

in the kprintf Log status and the debug log file, if configured.

## Known Issues

### Compiler issues

The constant propagation optimizations are still being debugged.  Most programs can
be safely run with constant propagation turned on while others may not.  Dead code
elimination is extremely buggy.  Some programs will appear to be working smoothly only
to freeze unexpectedly later on.  Play around with compiler options to determine the best
setting for a particular program.  The MPE3PacketHack is an option to enable in order to
resolve e.g. T3K to hang during level selection. It may also fix (yet unknown) hangs
in other apps/games.

### Pixel shader issues

The current pixel shader only fully supports pixel mode 2 (16-bit, no Z-buffer) & 4 (32-bit, no Z-buffer).
Others partially fall back to the CPU.

### Speed issues

This is a CPU intensive emulator and there is no way around that.

### NISE support

The emulator does not use a native implementation of the NISE mixer.  This means that
if your system cannot run Nuance reasonably fast, you can expect audio to sound
distorted and slow.  When running with
dynamic recompilation enabled, sound output is reasonably good and so audio interrupts
are enabled by default.  Audio interrupts can be disabled via the configuration file
but some programs may not work correctly if audio interrupts are not enabled.  In
particular, some games will wait for a particular sound to complete where the completion
is determined by NISE having had played all samples.  If audio interrupts are disabled,
NISE will never update the sample pointer and hence will never update the sound channel as
being available.  This is observable in Chomp, where running into a ghost will lock up the
game as the "player died" sound never "finishes" causing a wait loop to execute indefinitely.

### SYNTH support

At this point in time, libSYNTH is not supported.  Unlike libNISE, the synth code
configures the audio DAC to interrupt after each sample.  This is impossible to
emulate using a timer based approach.  It may be possible to use a performance timer
(e.g. timestamp counter) but this method of timing is not currently supported.

### Sound support

Audio is implemented using the miniaudio library (bundled) which auto-detects
PulseAudio, ALSA, WASAPI or other available backends.
The emulator supports all DAC configurations made possible through the Nuon BIOS audio routines.

### Multi-cycle instructions

The dot product, multiplication and load instructions take two cycles to
execute on the real Aries processor.  As with most emulators, this behavior
will not be emulated.  The implementations of these instructions will be such
there is an imaginary pipeline stall after a packet containing one of these
instructions.  Since code must be written to assume that there is no stall,
this implementation choice is not a problem since code should not be accessing
the destination register until two cycles after a dot product, multiply or
load is issued.
This can lead to problems though if code is optimized using the emulator,
and then tested on real Nuon HW.

### BIOS calls

The emulator supports BIOS calls but not all BIOS functions are implemented
at this time.  It is safe to call unimplemented BIOS functions but they will
not perform any useful actions.  Please read bios_support.txt for a list of
implemented BIOS calls.  The current BIOS implementation does not pass
pointer parameters that point to a remote MPE address.  For example, if
MPE3 makes a BIOS call that takes a pointer parameter, the pointer must point
to local memory on MPE3.

### MINIbios

Two minibios implementations allow MediaInitMPE to install the minibios on
any of the four MPEs.  The use of the minibios on MPEs other than MPE0 has
not been tested but should work.  The only difference between the two
implementations minibios and minibiosX is that minibiosX addresses are shifted
down by 4KB as required by the NISE library.

### DMA support

**DMALinear:**
All transfer modes have been implemented but only contiguous scalar mode has
been tested.  Byte mode transfers and contiguous word transfers are supported
but may not behave true to life since no example of non-scalar transfers is
known.  Skah_T has attempted to perform byte transfers on a real Nuon player
using what looked like reasonable DMA flags but the result was a locked up
player.  Without knowing how byte transfers are really supposed to work, I have
implemented byte mode in the same fashion as scalar mode except that the
destination stride is one word and the LENGTH/XSIZE field is interpreted as
the number of words to be transfered rather than the number of scalars to be
transfered.  In this mode, the source address and destination address are both
incremented by one word for each word or partial word transfered.  This routine
will work with both Other Bus and System Bus addresses.

**DMABiLinear:**
Bilinear DMA is supported but only standard left-to-right, top-to-bottom DMA
direction flags have been tested beyond what is used by demos and commercial
games.  Almost all pixel modes are supported with the exception of Z-value
only reads and writes.

DMA transfer is implemented as a loop of simple memory copies.  Transfers to
and from control register memory areas will not trigger the standard register
behavior that is obtained via load and store commands.

Single and batch mode transfers are allowed, but chained DMA transfers are not
yet implemented.

### Interrupts

Interrupts are fully supported, but hardware specific interrupts such as
VDP interrupts are not emulated.  Comm, timer, VDG and software interrupts
should behave as expected. Note though that timer, video and audio interrupts
(and also VSyncs) are triggered (mostly) at an 'ideal'/PC-based-timing, so that the
emulator will behave as an "over- or under-clocked" Nuon to Nuon-apps, which so far
all tested apps seem to be able to cope with though, as they feature some variant
of a syncing mechanism to not run too slow or fast. The benefit of doing emulation
like this is, that sound and gameplay will (mostly) run at the intended speed even
when running the emulator on a PC that will not be able to match 50/60 fps (full
cycle emulation speed).
In theory, this also matches the intended SDK philosophy that apps/games should
be forwards compatible for newer/faster processors.

### Comm Bus support

The communications bus is fully supported for communications between MPEs.
Similar to DMA implementation, the real world latency of the Comm Bus is not
emulated and it is possible for a target MPE to receive a sent packet in the
same cycle in which it was sent.  If no commrecv handlers take care of a received
packet, the packet is placed into a one entry queue for future retrieval.  If the
queue is full then the packet is dropped.

Most hardware comm bus targets are unimplemented.  Only the VDP clut and audio
configuration register read and write commands are supported.

### Memory management support

A simple memory manager is implemented that supports the necessary functionality
for the MemAlloc and MemFree BIOS calls.  Alignment requests may be any power
of two including one.  MemAlloc requests for kernel memory are not currently
allowed.  This should not be an issue because user applications are not
supposed to request kernel memory.  As with the real Nuon BIOS, the 64K range
starting at `$80000000` and the 640K range at `$80760000` is not made available to
user programs.

The current implementation of MemLocalScratch always returns `$20100D00` and a
size of 512 bytes.  This is due to a flaw in some commercially compiled versions
of MML2D where an environment variable field will overflow for values greater
than 3968 bytes.

### Framebuffer support

The 8-bit, 16 bit, and 32 bit pixel formats are supported, with or without Z.
A real Nuon system requires that the frame buffer resides in Main Bus SDRAM.
The emulator can also handle frame buffers in System Bus DRAM.  You can also
write directly to frame buffer memory when running emulated code but on a real
Nuon system, the frame buffer should only be accessed via DMA.  The emulator
stores the frame buffer in a standard linear fashion but the Nuon video
processor stores frame buffer data in an interleaved, cache optimized fashion
in order to speed up retrieval, particularly when filtering is used.

The emulator performs YCrCb to RGB color conversion using pixel shaders.
This allows complete hardware acceleration of
the color conversion process, saving several hundred million CPU cycles per
second that are now available for use by the processor emulation thread.

## Joystick support

By default, the keyboard may be used to control Controller slots 0 and 1 using
the following keys:

| Key | Function |
|-----|----------|
| A | Button Start |
| S | Button Nuon/Z |
| D | Button A |
| F | Button B |
| Q | Button LShoulder |
| T | Button RShoulder |
| W | Button C_Left |
| E | Button C_Down |
| R | Button C_Right |
| 3 | Button C_Up |
| Up | DPad Up |
| Down | DPad Down |
| Left | Dpad Left |
| Right | DPad Right |
| Z | switch between controller 0 and controller 1 |

The default controller bindings can be modified by including a
`[Controller1Mappings]` section in the configuration file, followed by a list of
`<Nuon Controller button> = <joystick or keyboard binding>` pairs. The available
controller button names are:

```
CPAD_UP
CPAD_RIGHT
CPAD_DOWN
CPAD_LEFT
A
B
L
R
DPAD_UP
DPAD_RIGHT
DPAD_DOWN
DPAD_LEFT
NUON
START
```

The format for joystick/keyboard bindings is:

```
<type>_<index>_<subindex>
```

Where `<type>` can be:

- **KEY** - A keyboard key
- **JOYBUT** - Joystick button
- **JOYAXIS** - Joystick axis, usually an analog stick axis.
- **JOYPOV** - Joystick point of view direction, e.g., a D-pad button.

`<index>` can take on the following values, depending on `<type>`:

- **KEY** - A win32 Virtual Keycode. See
  https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
  for a list of valid values. Note the value must be in decimal, not hex.
- **JOYBUT** - A Joystick button number.
- **JOYAXIS** - A Joystick axis index.
- **JOYPOV** - A Joystick POV control index. Usually 0.

`<subindex>` can take on the following values, depending on `<type>`:

- **KEY** - Must be `0`
- **JOYBUT** - Must be `0`
- **JOYAXIS** - `0` = axis min direction, `1` = axis max direction
- **JOYPOV** - `0` = up, `1` = right, `2` = down, `3` = left.

To figure which buttons/controls are which, you can use the "Properties"
button on the "Set up USB game controllers" control panel widget. Note the
buttons in the config file are indexed from zero, while the numbering in the
control panel widget starts at 1.

### Aries version

At the moment the emulator is hardwired to assume an Aries 2 generation chip.

## History

**05/30/2026 version 0.6.7:**
- FINALLY, T3K can be played with no hangs on music transitions, and with proper music looping!
  Also the level select hang (with DynamicCompiler enabled) is resolved (see GameCompatibility.txt/MPE3PacketHack-option though for the caveats)!
- Merlin Racing's AI drivers now follow the course as intended (with DynamicCompiler enabled).
- Add Linux port with CMake build system, X11/GLX backend and miniaudio audio output.
- Add libretro port.
- 32-bit build supports the x86 JIT dynamic recompiler on Linux via `__attribute__((fastcall))`.
- 64-bit builds employ asmjit instead.
- Static linking of glew (no more `glew32.dll` needed).
- Replace FMOD 3.75 with miniaudio. No more outdated FMOD SDK / `fmod.dll` dependency.
- Due to this, decouple host audio from Nuon DMA via a ring buffer (which was implicitly done by FMOD under the hood).
- Audio interrupts are kept intact while muted (matches previous behavior, needs to be verified on real HW).
- Drag and drop support for the UI.
- Can load games directly from ZIP/ISO files on Windows.
- On Linux additionally supports RAR/7z via FUSE tools.
- All "with carry" opcodes (=addwc/subwc/cmpwc variants) should now behave as written in the ISA spec.
- MSB JIT bug fixed.
- Fix bug in JIT versions of MULScalarShiftAcshift, MULImmediateShiftAcshift, MULScalarShiftScalar and MULImmediateShiftScalar (shift broken if left shift >= 32 used).
- Fix bug in JIT version of MULImmediateShiftLeftImmediate (wrong dependency used).
- Fix bug in ANDImmediateShiftScalar, ANDScalarShiftScalar, FTSTImmediateShiftScalar, FTSTScalarShiftScalar, ORImmediateShiftScalar, ORScalarShiftScalar, EORImmediateShiftScalar, EORScalarShiftScalar (shift broken if left shift == 32 used).
- Fix wrong flag setting for large numbers (highest bit set) in JIT versions of DECRc0 and DECRc1.
- Fix missing JIT implementations for loading odmactl,odmacptr,mdmactl,mdmacptr,comminfo,commctl,commxmit0/1/2/3,commrecv0/1/2/3 and configa/configb/dcachectl/icachectl.
- BTST is still not same as ISA spec (as apparently a real HW bug, at least on Aries 2 (=tested there)).
- Multiple bugs in the "CompilerConstantPropagation"-enabled path fixed, so enabled by default now, leading to more performance.
- Fix "_MPEAlloc()" logic to match original BIOS.
- Correct Audio Buffer sizes used for all configurations (via GetBufferSize()).
- Unfortunately, Tetris now sounds even worse than before.
- Fix (re)loading of 2ndary games: reset audio + MPE states.
- To make (at least) T3K work better, the whole MediaRead (and partially MediaWrite) implementation has been redone
  to better match the spec (incl. proper return values, proper callback mode handling, and not filling up buffers too early),
  at the tradeoff that now the loads actually need some time to arrive (incl. potential stutter).
- Fix "_MediaGetInfo()" byte-swapped fields.
- Fix uninitialized framebuffer (e.g. when starting fullscreen from command line).
- Optimize most JIT code that needs to do bswap/endian change.
- Enforce rz/rzi1/rzi2 (matching the Nuon hardware) to have bit 0 as 0 (due to 16-bit alignment).
- Some JIT instructions now are implemented correctly on non-SSE4.1 capable hardware (MUL_SVScalarShiftSvshift, MUL_SVRuShiftSvshift and MUL_SVRvShiftSvshift had vector-lane swaps for 2 components).
- Fix JIT for PVectorShiftSvshift (had wrong z component).
- Handle ITAGS and CTRL tags correctly in the JIT versions of StoreScalarLinear & StoreVectorLinear.
- Handle vdma* loads in JIT.
- Fix a potential correctness issue in the JIT MULScalarShiftLeftImmediate and MULImmediateShiftLeftImmediate with shifts > 32.
- Fix JIT RangeOnly and ModuloOnly register indices.
- instructiontest.cof has been updated with more tests (verified to match real HW / Samsung DVD-N501).

**03/21/2025 version 0.6.6:**
- Implement (bi)linear address mirroring properly and enable it.
- Optimize (bi)linear memory reads, and some memory stores.
- Optimize DMA transfers (especially all that are triggered by T3K).
- Fix linear DMA if Write & Dup & Direct mode.
- Fix linear DMA when writing to local control register.
- Fix missing 0x7F mask for shifts in certain mul/shift ops when using the dynamic recompiler.
- Implement BDMA_Type8_Read_0 (e.g. fixes Space Invaders 'Overlay' play mode).
- Add zero 'area' return to GetPointerToMemory(), as some games read 'invalid' mem regions (like $0 which returns 0 on Nuon HW).

**01/04/2024 version 0.6.5:**
- Fix loading of nuance.cfg when drag and drop is used.
- Hide mouse cursor when in fullscreen mode.
- Make rendering window behave like the others when trying to close it (e.g. clicking 'X' and Alt-F4 work now).
- Fix user breakpoints.
- Fix 16/16z pixel format bilinear DMA.
- Enable kprintf outputs (also new documentation about it within this readme file).
- Fix regression in code interpreter (shift+XXX opcodes).
- Slightly optimize code interpreter (ALU add+/sub+XXX opcodes).

**01/10/2023 version 0.6.4:**
- Fix command line file parsing, also drag and drop will now work properly.
- Fix wrong handling of global overlay alpha values > 0.
- Optimize OpenGL output shaders.
- Fix CRT-like shader for very high resolutions (e.g. 4K).
- Retweak CRT-like shader to be a bit more realistic compared to common CRT TVs back in the days.

**01/04/2023 version 0.6.3:**
- Add new (optional) postprocessing CRT-like shader (`[UseCRTshader]` in the .cfg), enabled by default, looks best in fullscreen.
- Its now possible to specify a file that should be loaded directly from the command line, e.g. `nuance.exe C:\NuonGame\nuon.run` — this will also automatically launch in fullscreen mode, too.
- Add new `[Controller1Mappings]` section in the .cfg along with DirectInput support for joypads/sticks and an additional UI dialog to configure keys/buttons.
- Fix a lot of problems with the MPE IRAM overlay areas and the code caching of these.
- Make MPE IRAM overlay caching more efficient.
- Merlin Racing now is playable (although the AI carts are still driving around randomly).
- Update status window on single stepping, too.
- Add missing registers to status window.
- Add debug output for BIOS calls.
- Add new `[AutomaticLoadPopup]` section to configure if the automatic file selection pops up on startup or not.

**11/27/2022 version 0.6.2:**
- Tweak audio interrupts some more.
- Correctly set DST.
- Some internal buffer overflow protection.
- Improve debugging output a bit.

**09/19/2021 version 0.6.1:**
- Optimizations.
- Fix some more opcode implementations.
- Improve Video- and SysTimer precision.

**5/28/2020, version 0.6.0:**
- Fix corrupted gfx in (at least) T3K.
- Fix wrong DMAs in Ballistic and Merlin Racing (so that these display mostly (always?) correct now).
- (Mostly) fix distorted sound.
- Optimizations all over the place (memory usage and performance).
- Always enable Pixel Shaders and fully support pixel mode 2 for more performance.
- Remove fields-per-second and always-update-video settings in the 'nuance.cfg'.
- Support Nuons VSyncing mechanism if a PC is emulating 'too fast'.
- Resolve a lot of hangs during gameplay, although this can still happen in some demanding situations (especially on low end PCs).
- Fix fullscreen toggle (via F1/ESC).
- Rudimentary support for x64/64bit compiles, needs to force-disable dynamic compiler though.
- Enable Reshade support by using double buffering.

**5/30/2007, version 0.5.0:**
- Fixed tons of compiler bugs.
- Fixed TimeToSleep routine, allowing Snake to work again.
- Added compiler support for all remaining instructions including delayed branches.
- Implemented syscall interface.
- Added SetISRExitHook BIOS call.
- Fixed problem with minibios MPE hanging when audio library initialized prior to sprite library.
- Added functionality required to support bootloader.

**2/05/2006, version 0.4.0:**
- Fixed most BIOS related bugs to the point where the only demos that do not run correctly are those that use libSYNTH or fancy z-buffer modes.
- Added support for FileOpen, FileClose, FileRead, FileWrite, FileLSeek, and FileStat.
- Added support for 4-bit DMA and 4-bit/8-bit framebuffer modes, fixing corrupted textures in Tetris.
- Implemented ability to recompile to native x86 machine code.

**10/16/2004, version 0.3.2:**
- Fixed critical IntSetVector errors which were breaking user ISRs, particularly comm handlers.
- Added support for VDG interrupts.
- Fixed code in video_m32_o32 fragment shader and made it the default fragment shader instead of video_m32.fs.
- Added Atmel AT49BV162A/163A flash emulation to duplicate the flash functionality of the Samsung N501.

**7/03/2004, version 0.3.1:**
- Fixed thread synchronization oversight that caused abnormally slow execution of all programs using multiple framebuffers, namely commercial games.
- Tweaked internal cache routines to significantly reduce cache invalidation overhead and greatly improve performance of programs with large working sets, e.g. most stuff running out of external memory on mpe3.

**6/30/2004, version 0.3.0:**
- Added dynamic recompiler with support for block coalescing, constant propagation and dead code elimination.
- Added support for standard non-rectangle textures.
- Added pixel shader support for pixel mode 4 (GLSL required, no overlay support).
- Added optional command line parameter for specifying configuration file.
- Added compiler options and video options to configuration file.

**4/03/2004, Version 0.2.2:**
- Fixed BIOS interrupt level1 comm handler bug introduced in the previous bug fix release.
- Switched from Extgl to Glew for OpenGL extensions management.

**3/24/2004, Version 0.2.1:**
- Repaired bug in BIOS implementation that caused getenv to always return NULL.

**3/22/2004, Version 0.2.0:**
- Fixed flag bug in MSB instruction handler.
- This fixes Decaying Orbit and the NISE audio library.
- Added audio playback support via the FMOD library.
- Updated the minibios bios implementation to fix potential issues with the NISE audio library.
- Added a second minibios implementation as required by the NISE audio library.
- Disabled stdout and stderr edit boxes due to memory sharing problems with FMOD.
- Added BIOS support for CommmSendRecvInfo, CommSendRecv, CommSendRecvInfo, TimerInit and SpinWait.
- Rewrote TimeToSleep in Nuon assembly to support a non-blocking version of the function that blocks only the MPE that called the function.

**11/25/2003, Version 0.1.0:**
- Major update from 0.0.1B.
- Honestly there are too many to list and I stopped keeping track somewhere in the middle.
- Dozens of critical bugs were squashed and the process, most of the remaining SDK demos began to work including MML2D, MML3D, M3DL and MGL demos.
- Most importantly, commercial games are now playable! In chronological order, the games that are playable are: Space Invaders XL, The Next Tetris, Merlin Racing and Tempest 3000. The Next Tetris suffers from texture corruption but the other three games are perfectly emulated.
- This release is a major milestone in the history of the emulator.

**11/01/2003, Version 0.0.1B:**
- Bugfix release of 0.0.1A.
- Added a memory display to the register window which allows MPE local memory, main bus RAM and system BUS ram to be examined in single step mode.
- The display will not update during normal emulation.
- Decoding and output dependency bugs were fixed for ST_S #nnnn,\<label D\>,LD_P \<label\>,Vk, LD_PZ \<label\>,Vk, and LD_SV \<label\>,Vk.
- Critical instruction handler bugs were fixed in the DOTP Vi,Vj,>>svshift,Sk and DOTP Vi,Vj,#m,Sk handlers.
- The behavior of the MPERun and MPERunThread BIOS routines were modified to behave more like the official implementation. This fixes graphics banding issues in the raytrace demo.
- MPEAlloc was rewritten, eliminating faulty logic that did not seem to be frequently encountered.
- Support for the mpectl register cycle type bits was added.
- A potential mpeWasReset bit bug was fixed.

**10/19/2003, Version 0.0.1A:**
- Bugfix release of 0.0.1.
- A scheduling bug caused the instruction scheduler to choose a non-optimal instruction order for packets containing three or more instructions. Fixing this bug drastically improves emulation performance for affected packets.
- A cut and paste error in the CMPWC immediate instruction handler triggered an attempt to write back the result of the comparison to an indeterminate register. This caused a program crash or register file corruption in some cases.
- The DecodeALU32 routine incorrectly decoded the operands for the SUBWC immediate reverse instruction causing corrupted program execution.
- The control panel window will now display a disassembly of the next instruction packet to be executed by the currently selected MPE.
- The disassembly output is updated whenever a new MPE is selected, an MPE is started or stopped, and when the single step button is used. The disassembly is not updated during normal emulation execution using the run button.

**10/12/2003, Version 0.0.1:**
- The first release of Nuance. Think of it as NuonEm out for vengeance.
- The emulator is now compiled under VC7 rather than BCB.
- The user interface now uses the Qt library in place of Win32.
- Additional optimizations make Nuance considerably faster than NuonEm 0.1.6F.
