111 Commits
Author SHA1 Message Date
SourMesen 8ac7e1df7d Lua: Fixed address value in memory callbacks when using memory types other than the default cpu memory type (#265)
Also fixed a few scenarios where the PPU memory write callbacks did not allow the Lua script to change the value about to be written (because the callback was called too late)
2026-08-27 19:00:22 +09:00
SourMesen 7f418e352a Clang: Fixed all compilation warnings (#241)
-Some warnings were suppressed (undefined-inline and return-type-c-linkage)
-Warnings as errors was enabled to make CI builds fail when warnings are introduced
-Slightly altered the behavior of SnesCpu::IdleOrRead, but this should match what ares does
2026-08-01 13:40:07 +09:00
SourMesen d76660c481 NES: Fixed BG/Sprite shifter edge cases (#190)
-Fixed BG shifter reload timing by moving it to the last dot of every 8-dot sequence (instead of the first dot). Fixes the "BG Serial In" test.
-Changed sprite shifter init/reset logic to allow edge cases where the shifter starts outputting pixels on a different scanline (when rendering was disabled during specific portions of the scanline, etc). Fixes the "Stale Sprite Shift Regs" test.
-Tweaked code in ProcessScanlineImpl, etc. to slightly improve performance
-Fixed missing PPU register mirror reads/writes in event viewer
2026-06-26 22:57:08 -07:00
FiskbitandSour e33b929dae NES: Add caching to sprite processing for performance (#148)
This adds some caching of whether we need to do sprite processing to reduce the overhead of checks when no work needs to be done. It improves performance by 1-2%.

Co-authored-by: Sour <[email protected]>
2026-05-28 00:43:20 -07:00
FiskbitandSour 1000562edd NES: Implement accurate sprite shifters & allow sprites on scanline 0 (#141)
* NES: Improve sprite fetch accuracy.

For sprite fetch, this improves in-range handling (which also helps with calculating the address to fetch) and stops treating sprites differently depending on whether we think they were valid based on sprite eval. The PPU uses just OAM2 during sprite fetch and not any other state from eval about whether sprites were good or not.

This change does not affect the behavior of any automated NES tests or AccuracyCoin. It improves performance slightly.

* NES: Allow sprites on scanline 0.

During pre-render, the PPU doesn't do OAM2 init or sprite eval, but it does do sprite fetch using the current contents of OAM2, which will usually be what's left over after sprite evaluation on scanline 239. This change allows these sprites to be drawn.

In AccuracyCoin, this change makes Mesen pass the Sprites on Scanline 0 test. However, it is detected as an RGB PPU because the skipped dot doesn't currently impact the position of the first sprite out of the shifters, which is a much more invasive change.

* NES: Improve sprite shifter accuracy.

* Fix hd pack player+builder logic (Sour)

* Improve dotskip accuracy without hurting performance.

* Change rendering check in pixel output (improves accuracy, sometimes performance).

---------

Co-authored-by: Sour <[email protected]>
2026-05-27 22:42:41 -07:00
Fiskbit 2d87f31942 NES: Reimplement PAL forced OAM refresh according to new research (#137)
* NES: Reimplement PAL forced OAM refresh according to new research.

On PAL, vblank is so long that OAM may decay during it. The PPU works around this by incrementing the OAM1 address every odd dot (delayed by 1, so happening on the following even dot) during scanlines 265-310. The PPU reads from OAM1 on every dot during vblank/fblank, so by repeatedly visiting all the addresses, it reads every row and keeps OAM fresh.

When implementing this, I found that OAM was corrupting reliably. This is because the forced refresh normally leaves the OAM1 address set to $8C when rendering begins, which triggers the 2C02E+ OAM corruption bug. However, all 3 types of OAM corruption are actually fixed on PAL, so this change also restricts OAM corruption to the NTSC console region.

All tests continue to pass with this change. blargg's oam_read test fails as it should, but not as severely as it does on real hardware. I'm not clear on why, but certainly part of it is that this change allows OAM1 to be incremented twice on a single dot. Adding hacky support for limiting this to just 1 increment makes it fail a little more severely, but still not as bad as on hardware (and that change is out of scope for this commit). My best guess right now is that it has to do with the precise timing of the $2004 writes, as the OAM write and increment delays depend on the timing of the end of the CPU write.

* NES: Dendy UM6561AF-2 has OAM corruption except on $2003 writes.

Based on my testing, frame-start (2C02E+ style) and mid-frame rendering toggle (NTSC style) OAM corruption happen on Dendy, but not $2003 write OAM corruption. So, this changes corruption emulation to match that.

Tested with oam_flicker_test, oam_flicker_test_reenable, oam_read, oam_stress, and Huge Insect.
2026-05-24 02:52:22 -07:00
Fiskbit 49eb0b3396 NES: Fix OAM2ADDR to be cleared on dot 257. (#131) 2026-05-20 06:24:18 -07:00
FiskbitandSour b82eb7b213 NES: Improve OAM corruption accuracy. (#122)
* NES: Improve OAM corruption accuracy.

Our understanding of OAM row corruption has significantly improved since Mesen's implementation of the feature that was based on oam_flicker_test.nes results. This change improves the accuracy of the two OAM corruption emulation options.

Primary OAM (OAM1) and secondary OAM (OAM2) live in the same block of memory, made up of 9-byte rows where the first 8 bytes are consecutive OAM1 bytes and the last byte is an OAM2 byte. The PPU accesses OAM on every dot. On some dots, it uses the OAM1 address ($2003), and on other dots, it uses its internal OAM2 address. If the address changes during an OAM access (the 2nd half of a dot) and this causes the selected row to change, then it can trigger either analog corruption (the new row gets 'random' data) or a row copy (the old row's 9 bytes are copied to the new row). More information can be found at nesdev.org/wiki/OAM_internals.

Address selection is fairly simple. When rendering is off, OAM1ADDR is always selected. When rendering is on, OAM1ADDR is selected on odd dots in 1-256, and otherwise OAM2ADDR is selected.

Corruption occurs on the NES in 3 situations:
1. Writing to $2003 on NTSC PPUs, because writes are not synchronized at all and so the CPU open bus value and the new value can both cause the row to change mid-access. Depending on the timing, this can do nothing, cause analog corruption, or cause row copy. This was fixed in PAL PPUs, but we don't know about Dendy.
2. Toggling rendering on an OAM2ADDR dot. Depending on the direction and the timing, this can do nothing or cause analog corruption of or row copy to the new row.
3. On 2C02E and later PPUs, having a row mismatch if rendering is enabled at the start of pre-render. This always causes a row copy from the OAM1ADDR row to the OAM2ADDR row and is required for Huge Insect to spawn enemies in level 1. (2C02C PPUs have some corruption in this situation, too, but it is not yet understood.)

This change adds support for OAM corruption in situations 1 and 2 using the "Enable PPU $2003/rendering-toggle OAM corruption" setting, which is off by default. This does not take alignment into account at all and only does row copy, not analog corruption. Recommended for developers, but probably undesirable for actual users. This setting was previously called "Enable PPU OAM row corruption emulation". Note that situation 1 ($2003 writes) is not perfectly matching blargg's oam_read test results in the most vulnerable alignment yet, suggesting there is more research to be done on this.

Situation 3 is now supported under the "Disable PPU frame-start OAM corruption (2C02D and earlier)" setting, so this corruption happens by default. Mesen was already doing some corruption here to support Huge Insect, with the previous version of this setting being called "Disable PPU OAMADDR bug emulation". These changes make the corruption more accurate and apply in more situations, so there is a chance it will break some user software, but because it is required for a game, we've opted to have it on by default. This feature should match hardware very closely, as it doesn't have the timing and analog aspects seen in situations 1 and 2.

To support these, sprite rendering was reworked a bit to more accurately manage the OAM1 and OAM2 addresses during rendering. This should make sprite rendering behavior more accurate when rendering is toggled mid-frame, although there are still inaccuracies that come up if you do this. The OAM2 address can also now be seen in the register viewer below $2003.

This was tested against a suite of NES tests, AccuracyCoin $2004 Stress Test, and oam_flicker_test.nes/oam_flicker_test_reenable.nes. The $2003-based corruption causes a few tests to change behavior when enabled (which is expected), but oam_read and related tests are not failing exactly right yet. Tests otherwise pass.

* Changes based on code review.

* Removed _spriteAddrL/_spriteAddrH members, use local variables instead.

* Simplify firstVisibleSpriteAddr assignment

---------

Co-authored-by: Sour <[email protected]>
2026-05-19 03:17:34 -07:00
Fiskbit 5b53458e81 NES: Update [OAM1ADDR] decay timestamp during vblank/fblank. (#120)
* NES: Update [OAM1ADDR] decay timestamp during vblank/fblank.

The NES accesses OAM on every single dot. When rendering is off, it uses OAM1ADDR for this, typically guaranteeing that a single row will not decay when rendering is disabled for an extended period of time. This means, for example, that sprite 0 should never decay in Battletoads despite its extended vblank.

This change updates the decay timestamp of the current OAM1ADDR row at the start of every blanking scanline, to simulate this behavior in the common case while minimizing performance impact.

* NES: Fix OAM decay counter array size.

Decay happens row-wise and there are 32 rows, so we should only be tracking 32 counters, not 64. The code only uses the first 32 counters.
2026-05-16 01:38:46 -07:00
NovaSquirrelandSour 325c78fcbd GB: Link cable support with two local consoles (#77)
* GB: Link cable support with two local consoles

* GB: Fix crash when color blending is enabled

* GB: Fix formatting

* GB: Link UI fixes, control fixes, audio fixes

Copied from Sour's branch. Also a separate change to use separate savefiles.

* GB: Try to avoid crashes from buffer overflows

* GB: Separate savefiles with linked multiplayer

* GB: Add support for faster link speed

* GB: Move enum to correct file

* GB: Refactor, move serial transfer to function

* -Fixed secondary console sometimes running far ahead of the main console when frame counters did not match (e.g because one console had their LCD disabled longer, etc.) This would cause buffer overflows in the audio buffer.
-Fixed screen tearing when both consoles are not perfectly in sync (because of the LCD being disabled for a different amount of time, etc.)
-Fixed main console not calling PlayQueuedAudio properly mid-frame
-Reuse VS Dualsystem code to merge audio/video when possible/simple and moved that to AvMergeUtilities

Some visual glitches can appear on the secondary screen (for GB) while rewinding, but this can't really be fixed.

* Fixed warning (unused local variable)

* Prevent loading single-console save states when in dual-console modes

* Disable debugger for VS DualSystem's subconsole. Fixes issues when debugging VS DualSystem games

* Code cleanup

* Rework solution to disable debugger on second console to improve performance
Added InternalRunFrame for nes & gb to avoid checking for the presence of the second console after each cpu instruction

* Don't enable the linked GB option by default

* Removed unused function

* Netplay: Force game to reload after updating emulation settings when connecting to the server (or when the host changes game)
This ensures that e.g the GB link cable setting is applied and that the game loads correctly, regardless of the client's link cable settings (otherwise the game could load without the link mode enabled, etc.)

---------

Co-authored-by: Sour <[email protected]>
2026-05-15 02:35:27 -07:00
Sour 687300a2d7 NES: Fixed issue with overclocking causing the APU to desynchronize from the CPU
This could cause DMC DMA to happen on the wrong cycle parity, causing issues with code that uses sprite DMA to align 4016 reads to prevent DMC DMA from corrupting the read value.
2026-04-30 22:33:05 +09:00
SourMesen e391fd8f9a Code: Add auto-formatting rules for C++ (clang-format) and enforce in CI via "clang-format" and "dotnet format" (#78)
* Code: Add auto-formatting rules for C++ projects (clang-format) and enforce code style via "clang-format" and "dotnet format"

* fix ui format warnings
2026-04-30 06:03:55 -07:00
100thCoin d51d5ce856 Made changes based on Fiskbit's comments
Added whitespace to the dummy read in branches.
Added the dummy read of RTS.
Fixed indentation in state machine delays.
2026-04-09 13:43:03 -04:00
100thCoin 005119afd0 Added comments to the bit plane initialization
I also swapped the order, so the high bit plane is set up first. This was done entirely so the comments flow better.
2026-04-09 12:54:25 -04:00
100thCoin 8cf98f2e52 Added the PPU DATA State Machine to the Serializer
This makes sure these variables get saved in savestates, and for rewind purposes, I assume.
2026-03-31 17:23:05 -04:00
100thCoin baa31e5eee Fixed the one dot delay between reads/writes of VRAM and v being incremented.
Moved the _needVideoRamIncrement if statement above the statements that set _needVideoRamIncrement, in order to re-introduce the one cycle delay.
2026-03-18 12:51:34 -04:00
100thCoin eb334d9f66 Added a State Machine for PPUDATA Writes
I also made small changes to the state machine logic. They delay is now 5 ppu cycles instead of 6. I don't know why I initially used 6.

While the state machine is running, it keeps re-enabling _needStateUpdate, otherwise the state machine doesn't run every cycle.
2026-03-18 12:43:48 -04:00
100thCoin ef0434e184 Updated shift register behavior
ShiftTileRegisters() only runs when rendering is enabled.
The high bit shift register also shifts in a 1. I'm unsure why this isn't passing the BG Serial IN test.
2026-03-17 17:45:19 -04:00
100thCoin 4adc78cc62 Various accuracy improvements
These changes make Mesen pass the following tests in the AccuracyCoin test ROM:
Implied Dummy Reads (RTS now dummy reads during the final CPU cycle.)
Branch Dummy Reads (Branches properly dummy read from the pre-incremented-PCH Address)
Address $2004 Behavior (Writes to $2004 during a visible scanline cause OAMADDR to be bitwise ANDed with $FC)
$2004 Stress Test (All OAM2 writes become reads after the OAM Address wraps around from $FF to $00)
$2007 Stress Test (Added a small delay to the PPU Read Buffer being updated, Sprite Fetch performs a second Nametable Fetch instead of an Attribute Table Fetch, The Dummy Nametable Fetch on dot 257 uses the correct value of the v register)
2026-03-17 17:18:20 -04:00
Sour ad548465c6 Debugger: NES - Added new "break on..." options
Invalid VRAM access, Invalid OAM write, DMA controller read, Unstable opcodes
2025-03-27 21:16:02 +09:00
Sour d32763e7f8 NES: Fixed regression in "remove sprite limit" feature that caused some sprites to be missing
Caused by recent accuracy improvements to sprite evaluation
2024-12-10 19:11:02 +09:00
Sour a394d05c97 NES: Fixed issue with new sprite eval bug emulation option that caused an incorrect fetch pattern when sprite overflow occurred
This could cause OAM decay to be detected even though it should never be possible for OAM to decay while rendering is enabled (sprite eval will refresh all OAM rows on each scanline)
2024-10-20 12:48:27 +09:00
Sour f90465c7cd NES: Count partially-copied sprites towards the sprite count for the next row 2024-10-19 13:31:25 +09:00
Sour ce4b3b8a56 NES: Added option to emulate sprite eval bug that causes unexpected pixels to be shown at X=255
This bug exists only on older PPU revisions (2C02B and earlier)
2024-10-19 10:15:35 +09:00
Sour 3dee924218 NES: Emulate another sprite evaluation quirk
Tweaks the H/L address bits increment/reset logic during evaluation to better match how hardware behaves (based on test rom). Also changes sprite 0 hits to consider sprite 0 to be the first sprite that sprite eval loads (based on oamaddr), even if the sprite is not actually the first entry in OAM
2024-10-11 18:01:20 +09:00
Sour 4c1579d8fd NES: Small performance improvements 2024-09-26 22:41:57 +09:00
Sour 6fcb3b6c05 NES: Decay ppu open bus values faster (3 frames instead of 30) 2024-09-21 16:16:32 +09:00
Sour 9f1be2683a NES: Fixed sprite evaluation emulation bug when oam address is misaligned
Test ROM shows that the lower bits of the OAM address are always reset to 0 when skipping to the next sprite
2024-09-14 10:23:47 +09:00
Sour 88da0b0c3f Debugger: Event Viewer - NES - Fixed incorrect NTSC borders in some scenarios 2024-09-13 15:45:27 +09:00
James Rowe 78130ed3bb NES: Fix MMC5 sprite display when using 8x16 mode with 8kb window and reduce sprite flicker enabled (#60) 2024-05-09 18:39:12 +09:00
Sour 08424ceba8 NES: Make OAM decay more obvious by displaying a diagonal line of sprites 2023-12-03 14:12:03 +09:00
Sour d357fd1c2c NES: Fixed missing save state flag when ppu warmup option is enabled 2023-08-10 17:06:28 +09:00
Sour 49f3859993 NES: Randomize palette ram when random ram is enabled 2023-05-15 00:20:17 -04:00
Sour 4df8a636f1 NES: Restored 2-phase ntsc filter when used on PAL games + fixed phases when overclocking is enabled 2023-03-27 18:04:05 -04:00
Sour 77acdab584 NES: Fixed phase for NTSC filters, allowing 3-phase pattern for Battletoads 2023-03-26 19:53:07 -04:00
Sour 88c0c76cbd NES: Fixed OAM decay bug when PPU reset is disabled
Also changed 'v' to be preserved on reset and vblank flag to be random if random power on state option is on
2023-03-03 23:09:02 -05:00
Sour 40833cf681 NES: Added option to emulate PPU "warmup" after reset 2023-03-03 22:51:58 -05:00
Sour bc1b979968 NES: Fixed PPU bus address on cycle 0 + improved MMC3 IRQ timing
Reproduces the flickering line that sometimes appears at the bottom of the screen in Wario's Woods (like hardware)
2023-02-25 01:00:36 -05:00
Sour 39a7b8b254 Debugger: NES - Added option to break when EXT mode is enabled
Turning this on can potentially damage the PPU and should be avoided
2023-02-18 15:59:14 -05:00
Sour 9e83a29b93 macOS: Fix compilation scripts/errors for macOS 2023-02-01 21:10:53 -05:00
Sour e96d6f3ca5 NES: Added HD pack builder tool 2022-12-29 18:28:33 +09:00
Sour 8563162da4 Debugger: NES - Various event viewer fixes
-Fixed incorrect ntsc border colors in some scenarios
-Fixed incorrect color/filtering for DMA writes (2004)
-Added "first register write" note to 2005/6 writes
-Fixed mapper reads using mapper write settings
2022-09-27 19:38:24 -04:00
Sour 7108bdde36 Refactoring - Moved some leftover files out of the root folder 2022-09-08 21:48:49 -04:00
Sour 152abf690b Rename stdafx.h to pch.h 2022-09-08 21:29:52 -04:00
Sour af6d4f0da2 Debugger: Refactoring for specific break options (+ added nes break on 2000 scroll glitch option) 2022-08-21 16:11:22 -04:00
Sour b6ce242495 NES: Fixed zapper color detection when grayscale/emphasis flags are enabled 2022-08-18 22:02:45 -04:00
Sour 76014f1271 Save states: Performance improvements (improves runahead performance) 2022-08-18 21:19:09 -04:00
Sour 6163158637 Debugger: Lua - Implemented getState + setState 2022-07-31 15:00:53 -04:00
Sour 623892d6c3 Fixed ram init logic to ensure the correct config option is used when loading a game 2022-07-25 22:04:44 -04:00
Sour 8354f48357 NES: Rename some functions/variables to match nomenclature used in the rest of the code 2022-07-24 20:31:19 -04:00