About the rom/dbg/asm files, it is a rather large project with a lot of assets, build-tools and game-specific things involved which I'm a bit hesitant to share in full. But I understand not having access to it will make reproing the issues difficult on your side. I will attempt to make a sensible and complex enough subset from the project, which builds smoothly and shows the issues I've seen so far.
And by the way, is there a way to make the "Profiler" refresh continuously rather than requiring a click on the "Refresh" button? The Profiler looks really useful, but for the case when time spent in functions can vary heavily based on the player's actions, it would be useful to see it update in real-time while playing the game.
Ah, yes that was it. Triggering the event that causes the third CHR-RAM page to be written fixed the problem so that the third macro invocation now looks the same. But yeah, it'd be useful to have some way to remove this distinction between executed/not executed code.Edit: To answer your edit about the 3rd macro: Mesen by default only disassembles code that the CPU has actually executed. There are options to change this though. In this case, I would assume the first 2 were executed while the debugger was running, but not the 3rd, which is why it's collapsed. Mesen uses CDL files to track the data/code segments - it's possible that the .dbg files contain enough information to produce a complete CDL file, I'd need to check.
The list control is pretty slow to refresh since it can contain hundreds of lines potentially. I could have a very slow auto-refresh feature if you need one (e.g every second or half second maybe?) That should be fast enough in this case?Bananmos wrote:And by the way, is there a way to make the "Profiler" refresh continuously rather than requiring a click on the "Refresh" button?
Check Options->Disassembly Options->"Disassemble..." and "Show...", it should be flexible enough for most use cases. You can also manually mark bytes as code/data/unknown by right-clicking in the code window or the memory viewerBananmos wrote:But yeah, it'd be useful to have some way to remove this distinction between executed/not executed code.
-Added a "Break on CPU Crash" option that will force the debugger to open and break the execution when the CPU executes an operation that will cause the CPU to halt. (to solve gauauu's use case)
-Added options to use a hardcoded 4-color grayscale palette in the Nametable & CHR viewers (subset of the functionality that tokumaru requested).
-Improved breakpoint display in the margin (added symbols to show when a breakpoint is conditional, or when the "mark" option is enabled)
-The profiler now auto-refreshes based on the memory tools' auto-refresh setting (at 0.1x the rate listed, so 6/3/1 fps)
-Fixed crash in the breakpoint list
-Fixed an evaluation bug with expressions (conditionals/watch expressions) when using parentheses.
I didn't check the DBG import issues yet, though.
Build here: download
Nice! Works great, thanks!Sour wrote:-Added options to use a hardcoded 4-color grayscale palette in the Nametable & CHR viewers (subset of the functionality that tokumaru requested).
- Left- or right-clicking in the breakpoint region of the debugger gives me the exception below.
System.NullReferenceException: Object reference not set to an instance of an object.
at Mesen.GUI.Debugger.Controls.ctrlBreakpoints.lstBreakpoints_MouseDown(Object sender, MouseEventArgs e)
at System.Windows.Forms.Control.OnMouseDown(MouseEventArgs e)
at System.Windows.Forms.ListView.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.ListView.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
- Trying to set a breakpoint on $2000 with the condition $E3 == 00 gives me the error below. This seems to be related to the condition I used, since a breakpoint on just $2000 is created without issue.
An unexpected error has occurred.
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at Mesen.GUI.InteropEmu.DebugSetBreakpoints(InteropBreakpoint breakpoints, UInt32 length) at Mesen.GUI.Debugger.BreakpointManager.SetBreakpoints() at Mesen.GUI.Debugger.BreakpointManager.AddBreakpoint(Breakpoint bp) at Mesen.GUI.Debugger.Controls.ctrlBreakpoints.mnuAddBreakpoint_Click(Object sender, EventArgs e) at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e) at System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e) at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e) at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e) at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea) at System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ToolStrip.WndProc(Message& m) at System.Windows.Forms.ToolStripDropDown.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at Mesen.GUI.Program.Main(String args)
- Write breakpoints on the CPU memory range $2000-2007 don't seem to actually trigger. This is definitely counter to my expectations. Is there really no way to break on PPU register writes?
- Both pausing and unpausing (currently mapped to escape) with the debugger open cause focus to change to the debugger window, and unpausing doesn't actually work (the emulator seems to run one instruction). I have the debugger configured not to break when opened or in focus.
- If the emulator is paused and the debugger is opened or closed, the emulator unpauses. Again, I have the debugger configured not to break when opened or in focus.
- The emulator can pause when in the background, but this even happens when the emulator's own tool windows are in focus, which seems like a problem when trying to use things like the event viewer. Is there a setting to treat these like the emulator window for the purposes of background status?
- When loading a game, the onscreen display tells me the emulator is applying a patch that doesn't (to my knowledge) exist, which made me have to double check that there was no patch by that name. For development purposes, I'd like to know that the ROM I loaded isn't being modified by the emulator, but I might still want this auto-patch feature for casual play. Can Mesen display this only if it's actually applying a patch?
- Clicking on a menu bar item when a window isn't in focus doesn't produce a menu dropdown, but I'm able to interact with other elements in this way.
- Having been using the FCEUX hex editor for ~15 years, I'm not very fond of Mesen's yet because I can't get close to the same density without making the text unreadably small, but I don't yet have a concrete suggestion here (Font? Row spacing? Dunno) and I might get used to it, anyway. It just feels frustrating right now because I can view rows $0000-0670 in FCEUX and only $0000-0430 in Mesen without scrolling, and the addresses I care about for my game are generally in the $0000-051F range.
- Is it expected that the image in the event viewer lags behind the main window by 2 frames when advancing frame-by-frame? Does this mean the events also 2 frames behind?
- Would it be possible to have a mark in the event viewer for the first dot that should be impacted by a PPU write?
- I find myself wanting to look at unidentified blocks in the debugger, which requires going to Options > Disassembly Options > Show... > Unidentified Code/Data to see the blocks and then again to hide them. I would much prefer if either this got a hotkey or it were possible to double click on block headings in the debugger to expand/collapse those individual blocks.
- Do breakpoint address fields need to be populated with 0 by default? It took me a bit before I realized I didn't need to delete the 0 before typing the address I wanted to break on, since the leading 0 is dropped.
- Held inputs appear to be dropped across reset and power cycles. My game has a feature where holding a button combination on reset displays a debug screen so crash information can be manually displayed if the game hangs in a way it can't detect as a crash. I'm unable to reach this screen in Mesen, but this does work in FCEUX and on real hardware.
- There doesn't seem to be a shortcut key for "Save State - Slot 8".
Problems aside, this looks pretty promising and I look forward to getting more familiar with it.
Edit: Would probably also be helpful if event viewer marks showed the CPU address responsible for the event.
Edit2: I would really like an option for left/right in the hex editor to go by bytes instead of nybbles. Moving by nybbles seems unnecessarily granular to me and makes manually indexing into tables more painful.
I've fixed/improved a number of things since the last build.
Here's a build with the latest changes: download
Let me know what you think. (And feel free to report more stuff if you find anything else)
Changelog: (sorry for the wall of text)
-Importing .dbg files now updates the CDL data, allowing the debugger to disassemble all the code ahead of time.
-Importing .dbg files for assembly projects that have file extensions other than .s should now work properly
-Improved the way the code window displays labels/comments inside data blocks
-Fixed an issue with hex numbers in the condition field (which was causing the crash)
-Breakpoints on registers should now be working again (was broken in one of my recent changes)
-Using the Pause button while the debugger is running should work better now (it won't bring the debugger to the front, and it will be able to resume if it was already paused)
-Clicking on menus/toolbars when the window is not in focus will now work properly without requiring an additional click (looks like this is a Win32 or WinForms issue)
-Added a "High Density Text" option in the hex editor (in the Text Size submenu) which reduces the blank space between lines - it should be relatively close to what FCEUX has. (also removed the Import/Export toolbar at the top since the same options are already in the File menu, and aren't useful enough to warrant the wasted space on the UI)
-Added a "Per-byte left/right navigation" option in the hex editor to force left/right keys to shift by a whole byte, rather than a single nibble.
-The 2-frame delay for the event viewer when stepping frame-by-frame was a bug - this is down to a 1-frame delay. The delay is due to the fact that the emulation is paused on scanline 240 (right after the picture is sent), while the event viewer refreshes later, on scanline -1, to allow the events that occur during VBlank to be shown. The picture & the events shown on it are always in sync.
-Added toggles for the verified/unidentified data blocks in the toolbar (and added shortcut keys: Alt-1 and Alt-2)
-Improved breakpoint window - invalid addresses now appear in red, 0 values now appear as blank when appropriate (and 0 otherwise)
-The event viewer's tooltips now display the value of the PC for the start of the current instruction.
This should fix most of the issues you've reported. The crash you were getting when clicking in the breakpoint list was fixed in the Feb 20th build. For the rest:
I'll try to see if this is something I can fix easily - but just so you know, the emulator's standard "Pause" feature is automatically deactivated when the debugger is opened. This is because it would interfere with breakpoints, etc (which is why there are differences in the pause behavior when the debugger is active)Fiskbit wrote:- If the emulator is paused and the debugger is opened or closed, the emulator unpauses.
It can be done, but it would need to be an additional option/flag, most likely. As it is, the option is meant to pause the game when you open option dialogs, etc. This is the behavior some people want/expect.Fiskbit wrote:The emulator can pause when in the background, but this even happens when the emulator's own tool windows are in focus
This is not supposed to happen - are you using a HD Pack? They can contain IPS patches which will automatically load when the HD Pack loads. Also, if the last time you ran the game you had an IPS patch loaded, close Mesen, and then launch the game via the game selection screen, it will automatically load that IPS patch again. The same is true for the "Recent Files" menu - it will display the IPS patch's name in brackets in the menu if an IPS file is linked to that recent file entry. If it's showing a specific filename when the game loads, that file should exist somewhere on your hard drive, and Mesen is patching the ROM with it.Fiskbit wrote:When loading a game, the onscreen display tells me the emulator is applying a patch that doesn't (to my knowledge) exist
Technically, the change takes effect on the next cycle after the mark (as far as the emulation core goes). This is not true for all flags, as some (e.g grayscale, for example) have small delays (this hasn't exactly been documented/fully proven yet), but the knowledge on the specifics is too lacking at the moment to try and display any sort of indicator.Fiskbit wrote:Would it be possible to have a mark in the event viewer for the first dot that should be impacted by a PPU write?
I can't reproduce this (at least, when I display the inputs for each frame with debug code, the buttons appear to be held down on every frame starting from the reset/power on). Was the debugger/etc opened while you were testing this? If you are able to send me the ROM, that would be helpful, too.Fiskbit wrote:Held inputs appear to be dropped across reset and power cycles
This is normal - save slot 8 is the auto-save slot, it is not meant to be written to manually. This is a relic of before key bindings could be changed, though. I will probably eventually set the save slots limit to 10 and then have an additional one called "Load State - Auto-save Slot" or such.Fiskbit wrote:There doesn't seem to be a shortcut key for "Save State - Slot 8".
You can disregard my comments on the IPS patching and on held directions being lost on reset; turns out I had accidentally loaded a ROM with the same name that was one directory up, which was accompanied by an IPS patch and also didn't have the crash feature in it. That does bring me to another issue, though, which is that Recent Files doesn't show a full ROM path, which makes it difficult to manage ROMs across directories. Right now, I have two ROMs in the list with the same name and no clear way to differentiate them, which makes me have to clear the history and open the ROM through the open dialog.
The hex editor changes are really nice. The new "Use per-byte left/right navigation" open doesn't work correctly, though; after overwriting one nybble of the current byte, the selection moves to the next byte. A couple other thoughts on the hex editor:
- I noticed it doesn't seem to have a paste option, which is something I find really useful in FCEUX. There, paste overwrites bytes with the contents of the clipboard.
- Along those lines, an undo feature when editing PRG-ROM would be handy. I frequently make tweaks to the ROM in the hex editor and often back them out with undo after observing their behavior. Although maybe this wouldn't be compatible with the code editing features in Mesen's debugger? This seems less important than the paste feature, since that'd at least allow pasting the original bytes back in place.
The pausing is definitely improved at least a bit, and if you do anything more there, it'd be really appreciated. For context, in FCEUX, I make heavy use of pausing and frame advance while debugging so I can get to the exact frame something occurs on, or to set up specific circumstances with frame-perfect inputs. Your explanation for why the behavior is different when the debugger is active makes sense, but the differences do seem inconvenient at times. For example, the "Run Single Frame" shortcut brings the debugger to the front each time it's pressed, like a breakpoint has been hit. It's not clear to me if there's some other intended mechanism for frame-by-frame play when debugging that I haven't yet discovered.
That makes sense. Thanks.Sour wrote:Technically, the change takes effect on the next cycle after the mark (as far as the emulation core goes). This is not true for all flags, as some (e.g grayscale, for example) have small delays (this hasn't exactly been documented/fully proven yet), but the knowledge on the specifics is too lacking at the moment to try and display any sort of indicator.
Would it be possible to add the PPU's t register (temporary VRAM address) to the debugger window?
Doesn't refreshing at -1 instead of 240 mean that the events shown in the vblank region are a frame ahead of the rest of the screen? Experimentally, this seems to be the case, as I see polling for sprite 0 hits in vblank 1 frame before I see it in the HUD in Zelda. Having events split between two frames when using frame advance seems surprising to me.Sour wrote:-The 2-frame delay for the event viewer when stepping frame-by-frame was a bug - this is down to a 1-frame delay. The delay is due to the fact that the emulation is paused on scanline 240 (right after the picture is sent), while the event viewer refreshes later, on scanline -1, to allow the events that occur during VBlank to be shown. The picture & the events shown on it are always in sync.
Also, I've seen cases where the event viewer doesn't update when stepping frame-by-frame, but I don't know how to reliably reproduce it.
Some more changes/fixes:
-Fixed the per-byte navigation option's behavior when editing values
-Added options to configure if the debugger comes to the front when a breakpoint/pause occurs (Options->Break On->Bring debugger to front [...])
-Added an option to display the full path of files in the recent files menu (Prefs->Advanced)
-Added paste support in the hex editor
-Added undo support for PRG ROM & CHR ROM edits. This undo is shared by all tools that can edit the PRG/CHR ROM (hex editor, assembler, chr editor), so pressing Undo will undo whatever the last change you did between those 3 tools. It's hardcoded to keep up to 100 undo steps (which means it'll take 100x the size of the ROM in memory - I could probably compress this to increase the number of undo levels if needed)
-Added the temporary vram address "t" to the console status display.
-Improved some pause-related issues with the debugger
Build with the changes: download
Let me know if there's anything else! Feature/workflow gaps vs FCEUX are one of the main things I am trying to fix, so all of this is definitely welcome!
Ah.. but Mesen does support Lua scripting :)Fiskbit wrote:At this point, I suspect the only major thing FCEUX has that this doesn't is LUA
I've done some more improvements here - there are new options in the "Break on..." menu to configure whether the debugger should come to the front when a breakpoint is hit, or when a pause occurs. "Run Single Frame" in this case counts as a pause. Also, if the game is paused when you open the debugger, it will stay paused (regardless of whether or not the "break on debugger open" option is enabled), and will revert to its paused state when closing the debugger (although it will run 1 frame before pausing again.Fiskbit wrote:The pausing is definitely improved at least a bit, and if you do anything more there, it'd be really appreciated.
You can also use the "Run One Frame" option in the debugger (F8), which will break the execution at the same cycle/scanline on the next frame. (vs the "run single frame" shortcut which will always break the execution on scanline 241, cycle 0)Fiskbit wrote:It's not clear to me if there's some other intended mechanism for frame-by-frame play when debugging that I haven't yet discovered.
I guess it depends how you're seeing things - the event viewer displays data top to bottom, in a chronological fashion - so the vblank section is the vblank where updates are being done in preparation for the next frame. Most other ways to display the events would have other issues (e.g events not being in chronological order, or vblank being at the top, which would mean the scanline numbers are out of order, etc.)Fiskbit wrote:Doesn't refreshing at -1 instead of 240 mean that the events shown in the vblank region are a frame ahead of the rest of the screen?
If you're holding down a key in the debugger (e.g F8), it's possible that the viewer doesn't update until you let go of the key, maybe that's what you were seeing?Fiskbit wrote:Also, I've seen cases where the event viewer doesn't update when stepping frame-by-frame, but I don't know how to reliably reproduce it.
EDIT: Found a small issue with the undo feature (could cause a crash due to multithreading) - I've reuploaded a new build to the same link that should fix the problem.
I totally overlooked the scripting feature, since I was glancing around for 'LUA'! Really great that that's in there; I'll work on converting my scripts over and will post if I encounter any issues with it.
Your reasoning for the event viewer behavior makes sense. The way I've always viewed things is that vblank is the start of the next frame rather than the end of the previous frame, so I'd probably prefer having scanline 240 at the top of the image, but this approach isn't perfect, either; I worked on a project many years back where rendering was disabled early on the bottom of the screen in order to have more vblank time, which would still look wrong with scanline 240 at the top.
Regarding the issue with the event viewer not always updating, I wasn't holding any keys (just pressing the Run Single Frame hotkey repeatedly), but I'm failing to reproduce it at the moment and it seemed pretty random when I was seeing it. If I see it again, I'll try to dig into it a bit more.
Some more issues I've encountered:
- Frame-by-frame with the debugger open prevents the vblank events from persisting in the event viewer.
- I can't completely figure out how the call stack is intended to work, and the documentation leads me to believe the behavior I'm seeing is buggy. In 2 games I've tried (Mega Man 1, Zelda 1), the call stack shows dozens of entries at any given time, with many of them being duplicates, even though the stack is small (e.g. SP == #$F9). In Zelda, for example, as soon as I first use frame advance, the call stack fills up with many "[nmi] $E484" entries.
- Entries on the call stack are removed when an RTS is encountered, not when it is executed. Hitting a breakpoint on an RTS seems like it make the call stack very misleading.
- Step Out in the debugger doesn't behave at all how I expect it to. As an example, in Zelda, if I set a breakpoint on $E53F (JSR $E62D), step into the function, and then step out, I would expect to be at $E542, but I'm instead at $E640. Using step out again takes me to $E544, one instruction further than I originally expected. What I think is happening: step out breaks after the first RTS that is executed, and it breaks one instruction too late (executes one instruction after the RTS). What I expect to happen: step out breaks when exiting the current function. So, when the current instruction is JSR, I would expect 'step into, step out' to be equivalent to 'step over'.
- If I break on a write to an address and then edit the register that's being stored into that address, the original value is still stored into memory.
- Writes in memory tools take effect nybble-by-nybble, so if I try to write a full byte while the game is running, it gets an intermediate value I never intended to write.
- Apparently saved states require the exact same ROM to be loaded, which is very inconvenient if I make a small change to my game and want to test it with those states. Can you add an option to load the state even if the ROM doesn't match?
- When a state fails to load because the ROM doesn't match, I get the following popup, which doesn't seem related to the action at all:
FDS bios not found. The bios is required to run FDS games.
Select bios file now?
- After interacting with the menu bar in any fashion, keyboard keys will open the drop down menu starting with that letter in addition to the expected functionality of controlling the game. This is mostly a problem after opening a ROM through Open or Recent Files; if I don't remember to click on the video region of the emulator, I'll accidentally open the debugger as soon as I start walking right.
- Sometimes when I'm dragging my cursor across menu bar items (File, Game, etc) while the drop downs are active, the drop downs suddenly become inactive. No idea how to reproduce this one; it currently seems random.
- Clicking on the video region of the emulator window when it's not the active window sometimes doesn't do anything, so it remains inactive and not in front. Clicking back and forth between the emulator and another window reproduces this quickly for me.
- Mousing over the Open dialog box causes it to jump to a new location if it's partially offscreen or even near enough the edge of the screen.
I saw that Mesen has CDL support, which I assume is the same CDL format used by FCEUX, since I didn't see any mention of it in the Mesen documentation. As a low-priority request, one feature I've been wanting to see for years is a more advanced code/data logger which could log information about how bytes are used rather than just whether they're code or data. The intent here would be to allow for better disassemblies with more automated labeling that can get closer to code that can be arbitrarily modified and reassembled without substantial manual labeling work. Examples of shortcomings right now include knowing whether data goes on to be used as a high or low pointer byte for an indirect table or jump (and what byte it's paired with), code and data that get relocated to RAM before being used, and tracking the bounds of tables. It's been a few years since I was doing CDL-assisted disassembly, but I also recall shortcomings with FCEUX's logs where mapper writes showed as data and code operands were logged just like opcodes (so operands that were also executed as opcodes weren't logged in any special way).
Edit: Is there a quick way to go to the current PC, or do I have to use Ctrl+G and type the address?
you can double click on the top of the call stackFiskbit wrote:Is there a quick way to go to the current PC, or do I have to use Ctrl+G and type the address?
This is normal/a limitation - the frame-by-frame feature breaks on scanline 241, just before inputs are read - this allows the user to setup inputs for the next frame. But on scanline 241, vblank did not execute yet, so there is no way to display the vblank events. A workaround would be to setup a breakpoint on the last scanline+cycle of the frame and use that into of "run single frame".Fiskbit wrote:- Frame-by-frame with the debugger open prevents the vblank events from persisting in the event viewer.
This is hard to fix - the debugger has no knowledge of where the value being written comes from. By the time a write breakpoint occurs, the instruction is already halfway completed and the value that is about to be written to cannot be changed (although, with Lua scripting, it should be possible to change the write value)- If I break on a write to an address and then edit the register that's being stored into that address, the original value is still stored into memory.
I understand the problem, but the alternative is also problematic in terms of usability - there is no simple way to convey to a user that the first character they wrote actually has no impact until they write another character or move away (despite the hex editor showing the "new" value). I actually changed the code and tried it out, but I'm not convinced this is more intuitive (maybe as an option?).Writes in memory tools take effect nybble-by-nybble
Like upsilandre said, the simplest way is to double-click at the top of the callstack. Other than that, there is also a "Show Next Statement" feature binded to Alt-* which has the same effect.Edit: Is there a quick way to go to the current PC, or do I have to use Ctrl+G and type the address?
-Event viewer not updating: This was probably due to the "Run Single Frame" feature stopping at random points in the picture when the debugger is opened (this is no longer the case since the previous build, always breaks on scanline 241)
-Save states requiring the same ROM: I'll see about this - will need to at least validate that the ROM is the same mapper, etc, otherwise allowing this could end up crashing the emulator, etc.
-The FDS prompt when trying to load a savestate for a rom that can't be found is fixed
-The callstack bug when breaking on RTS instructions should be fixed, and the step out feature should be working properly now.
-Menu bar staying active: I get the same problem and agree it's annoying - Can't think of a simple fix for it at the moment (e.g one that is low in terms of maintenance in the future), but I'll try to think of a general solution.
-Cursor across the menu suddenly not working: Haven't been able to reproduce this
-Clicking on the window not bringing it to the front: Same, can't repro, and I tried clicking pretty fast.
-Open file dialog jumping: This is standard Windows behavior - I'd imagine all programs using the standard windows dialogs do the same (FCEUX does at least)
-Callstack in Zelda/MM: As far as I know, some games do not behave "nicely" and may sometimes not call RTS/RTI a matching number of times for each JSR call and NMI. This "corrupts" the callstack (which is not based on the CPU's stack at all). Fixing this would be tricky/impossible, since code is not required to call RTS/RTI to work properly. A good portion of games should be working properly, though.
(Haven't really made any notable changes worth a new build just yet - I'll post one when I get some more things done)
(coming back to this really much later)Sour wrote:Not too sure I'm understanding what you mean - maybe adding an optional grid every X clocks would do it? Slightly unrelated, but I was also thinking of changing the background color for the scanlines where it is safe to run the sprite DMA (which is slightly different between PAL & NTSC, afaik)lidnariq wrote:Although maybe some kind of ruler during hblank might possibly be...
I think just showing bounds of when it's safe to do certain things? But on a scanline-to-scanline basis, most of these edges fall into two places- 1- the rightmost edge of active video, or 2- dot 320. And I'm not clear if having these edges displayed will be useful enough to balance out having to explain why there's a weird extra line, especially since the user can use the breakpoint functionality to add it themselves.
How would your separately tracked call stack treat the message dispatch idiom used in several of my own games?Sour wrote:-Callstack in Zelda/MM: As far as I know, some games do not behave "nicely" and may sometimes not call RTS/RTI a matching number of times for each JSR call and NMI. This "corrupts" the callstack (which is not based on the CPU's stack at all). Fixing this would be tricky/impossible, since code is not required to call RTS/RTI to work properly. A good portion of games should be working properly, though.
Code: Select all
move_actor: ldy actor_class,x lda move_procs+1,y pha lda move_procs+0,y pha rts
Consider the following algorithm. Would it work in more cases?
1. On each addition to the call stack, save S.
2. After any RTS or RTI, discard call stack elements whose S is less than the current S.