So I am making this thread as sorting things out in FlapPing is proving far more difficult then I thought. So I'll use this to sort out my thoughts/findings and if anyone with any sort of knowledge or can offer any insights please do so.
I will be using this opening post as a Tracker for things I find.
FIXED!
Midscanline playfield register updates are not immediately latched by TIA. This is why FlapPing intro screen doesn't draw correctly.
Player graphics register updates are also not immediately latched by TIA. Similar to above, this is why the 'O' in 'POWER' in H.E.R.O. isn't drawn correctly.
Double and Triple sized players take an extra color clock to draw. This is why FlapPing doesn't sync and the countdown numbers are slightly misaligned. Since this also effects collisions it is a pretty serious bug.
Special instructions that modify player resets that were borrowed from 7800 code are not necessary for the 2600. This is what casues Halo 2600 to be unwinnable and the car in Dragster to break into pieces.
Writes to timer should cause immediate decrements
RESPs in HBlank should set players at 3 pixels in not 5.
writes to ENAM registers have a one pixel delay in registering
check PAL timing. Lag frames are added when there is an off-nominal number of scanlines per frame, this is tied closely to frame definition but not an independent problem.
sound emulation.
TO DO
Implement HBLank cancelling (but need something to test it on)
Frame definition and input mismatch. This is not technically a bug, rather an architecture choice, but nonetheles produces some trouble in edge cases, such as the paddle always rising in FlapPing
investigate 6532 start up state. Is it uninitialized?
investigate HMove interaction with RESP commands. It looks like there is some trouble with RESP and Hmove happening on the same clock
BONUS
Cosmic Ark stars. Probably some analog or very low level timing effects, but is not currently understood. This seems to be tied to TIA revision. Unlikely to be resolved without circuit analysis of each revision.
second look at delays and timings. Many timing delays give correct results but it's not clear why they would be true from a low level. Partially resolved with revised HMOVE code, but questions remain particularly in RESB and PF.
Ok first off let's start with the title screen drawing bug:
So I stared at BizHawk's code for a long time trying to find the reason that the 'P' in 'Ping' is not being outlined properly, but in the end, it just seems like it's doing everything properly. This is strange, as other emulator's draw the screen as intended with no problems. So I looked at the game code:
F19D 85 STA $02
F19F BD LDA $FE9E,X *
F1A2 85 STA $0D
F1A4 BD LDA $FEC1,X *
F1A7 85 STA $0E
F1A9 BD LDA $FEE4,X *
F1AC 85 STA $0F
F1AE EA NOP
F1AF EA NOP
F1B0 EA NOP
F1B1 BD LDA $FF07,X *
F1B4 85 STA $0D
F1B6 BD LDA $FF2A,X *
F1B9 85 STA $0E
F1BB BD LDA $FF4D,X *
F1BE 85 STA $0F
The first instruction, STA $02 calls a WSYNC which halts the CPU until a scanline is finished drawing. So the next LDA instruction happens only once horizontal blanking starts. This loop loads one line of the title screen. (The addresses $0D-F are the playfield registers that tell the TIA what to draw.)
The above code (minus the WSYNC) takes 48 cycles to execute. There are 3 color clocks (i.e. pixels) per cycle, which means we have 144 color clocks worth of code there. Horiztontal blanking takes 68 of those clocks, meaning we end at pixel 76 on the screen. The point here is that F1BE has stored a new value to the playfield register before the TIA has had time to draw the first half (80 pxels) of the screen. So the expected behavior is that the last block of 4 pixels will be drawn with the new values (the second half of the screen.) And this is what we see here, As that vertical bar is clearly a copy of the one on the right edge of the title.
So I can only conclude that BizHawk is correct, and this is what should actually be displayed. It's not even hard to test, the next instruction after STA $0F is DEY, and if you just swap the order of these instructions, you give the TIA 6 extra clocks and it gets safely past the half way mark.
Stella seems to be cheating a bit here, as in Debug mode you can see that the TIA has drawn past the half way mark despite the hsync counter and the cycle counter both agreeing that they haven't made it that far. I can't explain this behavior.
This is all very strange, but if anyone has any reason to believe that Stella is doing things correctly, or has pictures of this game being played on a real console to prove things one way or another, please let me know. I will also post asking this on AtariAge (once they let me post.) I also tried e-mailing Kirk Israel, but the address (flapping@alienbill.com) returns a 'no such user' error.
well a helpful poster at AtariAge gave a helpful answer!
So it looks like a quick patch to BizHawk to prevent midscanline updates to the playfield registers before this point is all that is needed.
It pays to ask the experts!
Alright! Turns out the number positioning bug is actually a pretty simple bug and was relatively easy to track down.
The problem is that there is an extra color clock needed to position double and quad size players. Pterry and the countdown numbers are double sized, and BizHawk isn't giving them that one pixel shift to the right.
See this thread for discussion and even test ROM results that show this:
http://atariage.com/forums/topic/239890-respx-nusizx-and-player-positioning/
Looks like a simple fix, hopefully this also fixes the car positioning bug in Dragster.
EDIT: I should clarify that it's not their position that changes, it just takes one extra clock to start drawing them. BizHawk looks like it already has the one pixel delay built in for normal sized players, it just needs one more for double/triple sized ones.
I have also found out why your paddle always rises after pressing start in FlapPing (after an otherwise normal startup)
The game actually only does a very short (9 scanline) frame after the end of the previous frame when it determines the button is pressed and it's time to start.
The problem is that BizHawk is detecting this frame exists as a seperate frame, (giving it it's own frame in TASstudio piano role as well giving a blank screen i.e. no video input) but at the same time is carrying over the input from the previous frame into it. This is easily demonstrated in Stella by just doing the same thing and carrying the button press through those 9 scanlines.
I don't know where this matmatch is happening in the code, I'm having a hard time following the C#, but this is the effect anyway.
else if (maskedAddr == 0x11) // RESP1
{
// Borrowed from EMU7800. Apparently resetting between 68 and 76 has strange results.
// This fixes some graphic glitches with Frostbite
if (_hsyncCnt < 69)
{
_player1.HPosCnt = 0;
_player1.ResetCnt = 0;
_player1.Reset = true;
}
else if (_hsyncCnt == 69)
{
_player1.ResetCnt = 3;
}
else if (_hsyncCnt == 72)
{
_player1.ResetCnt = 2;
}
else if (_hsyncCnt == 75)
{
_player1.ResetCnt = 1;
}
else
This piece of code is responsible for both the exploding car in Dragster and the fact that Halo 2600 cannot be completed in BizHawk.
When I change the 3-2-1 to zeros, everything works fine. So whatever the 7800 is doing with the TIA seems to be specific to the 7800 and does not extend to the 2600.
I also have found no reason to believe these values are true from looking at any of the 2600 documentation.
So looks like another quick fix and another annoying bug is busted!
EDIT: Update on this, it also fixes Smurfs in that the game can now be beaten. I also looked at the moving houses in River Raid and I think the double sized player bug fix and/or the player register write delay will solve that problem, and likely the graphical glitch in Grand Prix as well.
I had some time to look over some of the other 2600 runs and see if any of them are impacted by these bugs. I found a couple that had tell tale signs of left edge of the screen glitchiness / double sized player bug.
[2898] A2600 Airlock by Gay in 01:51.68
In the encode of this run you can see that towards the left edge of the screen the player suddenly shifts a few pixels. This is not present in Stella. This is caused by the 3-2-1 bug. The run de-syncs after the bug is removed.
[2228] A2600 Bobby is Going Home by Lollorcaust in 01:16.13
You can see similar shifts in the encode of this run that shouldn't be there.
[2500] A2600 E.T.: The Extra-Terrestrial by CoolKirby in 00:25.13
ET's spaceship is incorrectly placed in the intro cutscene. Being a double sized player, it is one pixel too far to the left. Doesn't look like a sync issue though.
Thanks!
Okay, so Pterry's strange behavior in Flapping is being caused by some type of strange timing bug.
The short version of what's happening is that the address tracking Pterry's position that should be changing every frame is being paused occasionally. On Pterry's first loop going left, it pauses at 0x25. So Pterry takes 259 frames to make a complete loop in bizhawk but only 258 frames to make a complete loop in Stella.
It doesn't consistently pause at this point, it seems to shift with each loop, but always happens once per loop.
I tried looking at a trace log to find out what was going on but nothing shows up in the trace log that indicates a pause. I did see some strange trace log behavior though:
STA $02 is a WSYNC, so as expected the cpu gets paused at the LDA $E1. But then at the end of the WSYNC, the instruction address suddenly jumps to F926 and the cycle counter DECREASES by 33510 cycles. 4411204 is actually where the trace originally started. I think this is a new bug introduced into trace logger in this version since it doesn't happen on previous versions. At any rate it looks like it's just a trace logger bug not related to other core bugs.
Previous versions (I tested on 1.11.1) still exhibit this timing bug so it wasn't a result of any of the recent patches. But I don't know what the origin of it is, quite a strange bug indeed.
The only hint I have is that even though Pterry's position is paused in RAM, his position on screen is still changing.
Sometimes the best test is simply to do nothing!
I loaded up FlapPing and just let it run. Then I noticed there were some strange lag frames every so often on the title screen.
They occur at frame:
64, 327, 590, 853, 1116, ....
The important point is that they are all separated by 263. This is an important clue since the number of scanlines in a nominal frame is 262.
So my theory here is that there must be an off-by-one error happening somewhere in the code.
I don't know where or why, but this seems like a pretty solid lead.
So I think I found where the timing bug is that causes random lag frames.
From this document we get:
This is what Stella does as well, but in BizHawk's 6532 we have:
So what it does is write the new value but sets the interval timer already at the top of the interval. So basically this gives 1 extra Tick every time there is a write to the clock. This happens once per frame, and this interval is one scanline, so naturally after every 262 of those we see the timing error.
I am pretty sure the fix is to just put: Timer.PrescalerCount = 0, which will immediately decrement it as spec'd.
I did so, and indeed the random lag frames vanished, hurray!
But, this STILL didn't fix Pterry's buggy behavior, and I am at a loss as to how to fix it or where the bug is.
After looking over the 6532 datasheet it looks like you are correct that there is an off by one bug in that code. Your change looks like the right way to fix it, so I went ahead and committed it.
After looking over the 6532 datasheet it looks like you are correct that there is an off by one bug in that code. Your change looks like the right way to fix it, so I went ahead and committed it.
Great! Any ideas on the other bug with Pterry? I have no leads and no ideas.
But on the up side, I just tested the timing fix in Dragster and it with it you can change gears earlier! You can start at frame 164 instead of 167, and from my previous testing this should be enough to improve the time. Maybe that riddle might be close to being solved!
EDIT: Oh yeah, the timer is also set at the top of the interval at initialization too. In Stella it is set at the bottom. I am not sure if there is a correct setting or if this is undefined, just thought I'd mention it.
I believe ptrerry's random pixel shifts are caused by a bug in RESP.
I followed the game code and it turns out Pterry's buggy movements happen right when the RESP function changes from happening 'on screen' to happening in the HBlank region.
Looking over BizHawk, it seems the variable at play is:
Setting _player1.ResetCnt = 2 instead fixes the problem. (needs to happen for player 0 too of course)
Writing any value to these addresses sets the associated objects horizontal position equal to the current position of the cathode ray beam, if the write takes place anywhere within horizontal blanking then the position is set to the left edge of the screen (plus a few pixels towards right: 3 pixels for P0/P1...
So when it started at 0 the loop in the TIA that reset the player put it 2 pixels too high, since it counts from 0 to 4.
I'm not 100% sure this fix is correct, but it makes the game behave as it does in Stella, so I'm at least somewhat confident it is.
Joined: 11/13/2006
Posts: 2822
Location: Northern California
Alyosha wrote:
But on the up side, I just tested the timing fix in Dragster and it with it you can change gears earlier! You can start at frame 164 instead of 167, and from my previous testing this should be enough to improve the time. Maybe that riddle might be close to being solved!
Not at all, unfortunately. You just get 5.57 a few frames faster with the timing fix.
EDIT: Also, implementing the exploding car fix just seems to make the car constantly explode, but I'm just going to chalk that up to an error on my part.
TASvideos Admin and acting Senior Judge 💙 Currently unable to dedicate a lot of time to the site, taking care of family.
Now infrequently posting on BlueskywarmCabin wrote:
You shouldn't need a degree in computer science to get into this hobby.
Awww, I was really hoping that 5.51 would work too, back to the drawing board I guess.
Yeah the exploding car fix should work perfectly. Just change the 3-2-1 in that bit of code to be zeroes, oh and remember to do it for both players.
I can confirm that the double sized player bug did not affect the sync of the published E.T.: The Extra-Terrestrial run. (The run does not sync on BizHawk 1.7.0 or later as it is though.)
I want to say thank you for fixing all those tough bugs - I was thinking of running Halo 2600 several months ago and now it should finally be possible.
Will your fixes be implemented into the next BizHawk?
I can confirm that the double sized player bug did not affect the sync of the published E.T.: The Extra-Terrestrial run. (The run does not sync on BizHawk 1.7.0 or later as it is though.)
I want to say thank you for fixing all those tough bugs - I was thinking of running Halo 2600 several months ago and now it should finally be possible.
Will your fixes be implemented into the next BizHawk?
Not sure, once micro500 or some other knowledgeable person confirms these findings are correct, it's easy to fix a few of the bugs just by changing some constants. The latch delay type bugs are more difficult though will probably take some time to sort everything out. Halo 2600 should work with the easy fixes though.
Yeah any run like E.T. made before the switch to fixed length frames / inputs will be difficult to reconcile with any new runs made. I thought about making some test runs but currently don't have the time.
So I happened across an emulator bug that might hopefully also shed light on Cosmic Arc stars and properly emulating quirky HMove instructions.
I was browsing other Atari 2600 games that were known to behave badly in BizHawk looking at the list here. I looked at Donkey Kong Jr since it had some weird gameplay bug listed as the error.
The picture below is 4 consecutive movement frames. On frame 3 you can see quite clearly that DK gets pushed to the left rather far before snapping back to the right the next time.
What's happening here is (I think) related to the warning not to change HMove registers until 24 CPU cycles after HMove is executed, here is the relevant code:
So what we have is an HMove immediately following a WSYNC, this is the expected behavior, but then we have only 22 cycles in between that and the following HMP0 instead of the expected 24.
Quoting hardware notes we have:
In theory then the side effects of modifying the HMxx registers
during HMOVE should be quite straight-forward. If the internal
counter has not yet reached the value in HMxx, a new value greater
than this (in 0-15 terms) will work normally. Conversely, if
the counter has already reached the value in HMxx, new values
will have no effect because the latch will have been cleared.
Much more interesting is this: if the counter has not yet
reached the value in HMxx (or has reached it but not yet
commited the comparison) and a value with at least one bit
in common with all remaining internal counter states is
written (zeros or ones), the stopping condition will never be
reached and the object will be moved a full 15 pixels left.
In addition to this, the HMOVE will complete without clearing
the "more movement required" latch, and so will continue to send
an additional clock signal every 4 CLK (during visible and
non-visible parts of the scanline) until another HMOVE operation
clears the latch. The HMCLR command does not reset these latches.
This shove to the left only happens here when HMP0 is 7, the same code is obviously running constantly but only this value makes the big shove to the left happen.
Stella seems to cheat in this case and instantly applies the HMOVE and ignores how long actual execution should take.
This shove to the left doesn't happen on console (and makes the game unwinnable in BizHawk) so sorting this out seems like a good step in understanding this HMove stuff.
Either that or it's a simple bug that I just can't see yet.
Well I have a possible solution that correctly displays cosmic Ark stars.
The problem was that the TIA code was looping the _Hmove counter instead of just resetting it after it reached 15. The effect of this is that the latch that normally would never would be cleared would just be cleared on the next pass of the counter. This prevented the stars from forming.
This 'fix' breaks DK JR though (well, in a different way) so I'll be consulting with micro500 to work out what's happening. I'm pretty sure the overall idea is correct though.
Here is a brief video though:
Link to video
Perhaps we are close to getting the star effect in a real non-hackish way!
EDIT: found the bug the messes up DK JR
if (_hmove.HMoveDelayCnt < 6)
{
_hmove.HMoveDelayCnt++;
}
if (_hmove.HMoveDelayCnt == 6)
{
_hmove.HMoveDelayCnt++;
_hmove.HMoveCnt = 0;
_hmove.DecCntEnabled = true;
Those 6's should be 5's. This 1 extra clock delay is what's breaking DK JR.
The stars still don't display exactly as expected so more research is needed there, but things seem to be shaping up.
EDIT2: I forked all my changes into github here: https://github.com/alyosha-tas/BizHawk
This contains the fixes for pterry, the ENAM fix, the starfield, DK jr fix, 3-2-1 fix.
Success!
After a bit of sleuthing a discovered what was missing to make the star pattern work correctly.
From the same hardware notes page as above we have:
I mentioned above that HMOVE sends extra clock pulses down
the same clock lines that are usually used during the visible
part of the scanline. In theory this means that performing a
HMOVE during the visible part of the scanline should have no
effect. However, looking at how the various clock signals
interact, I suspect it is possible. I did some preliminary
experiments (on a 2600 Jr) at some point, and I seem to
remember having some success.
So the key is that HMove is only effective during HBlank period. The existing code makes it happen during the entire scanline. Normally this is inconsequential since HMove ends correctly, but during this glitchy case it needs to be taken into account. Doing so gives the correct pattern, as can be seen in the video below.
Link to video
This still isn't quite the end of the story though. It seems there are some analog effects happening with the timer pulses using the same line, I don't think those have been effectively documented anywhere so this might be the as far as things go for a while. On the up side this is a proper implementation and should be correct. It still doesn't look like Stella, but at this point I'm not sure exactly why Stella uses the exact pattern it does.
I have updated my code in the github to reflect all current changes.
Wow congrats!
For Stella, I'm not sure why. Given how it was mentioned that it uses a high level approach rather than a lower one, it (may be) the case that the devs simply made a random starfield effect and assumed it looked "close enough". Could be wrong however.
Wow congrats!
For Stella, I'm not sure why. Given how it was mentioned that it uses a high level approach rather than a lower one, it (may be) the case that the devs simply made a random starfield effect and assumed it looked "close enough". Could be wrong however.
Doing a bit of research it seems that the pattern in Stella was hard coded to match observed behavior. I have no idea why this behavior occurs at this time, but this commercial of the game pretty clearly shows the pattern in Stella as opposed to the uniform one produced by the understood effect:
Link to video
This is what mirco500 was trying to figure out with his work I believe (the basic effect of not resetting movement latches is straight forward and pretty well understood)
Anyway I made some more clean up and commits to my fork. So if anyone wants to compile and play I put the link in the opening post.
So I have finally fixed the original bug that got me interested in all of this. This implements the same play field delays that Stella uses. While I don't understand why they would be true at a low level, they none the less have high compatibility and I haven't seen any deficiencies in my testing.
Emulator Coder, Site Developer, Site Owner, Expert player
(3573)
Joined: 11/3/2004
Posts: 4754
Location: Tennessee
Ideally you would create a fork of bizhawk on github, make this change and do a pull request.
If all of that is well outside your comfort zone, work with me and we will find a way to get this change integrated.
And btw, I'm really impressed with the work you've done with atariHawk, and I'm really glad you have. Good Atari emulation is something I find valuable.
I did make a fork of Bizhawk (linked in opening post) that has all my current changes, but that is as far as I know how to do. I don't really understand the pull request thing, but sure just tell me what to click on and everything can be integrated.
However I am still waiting for confirmation on the most critical fix which is the ENAM delay in the current FlapPing submission. Aside from just following Stella I have no concrete proof if it is true or not. I asked on AtariAge but have no replies yet. So unless I get something certain there or a console verification, integration into the official BizHawk might have to wait a bit, I wouldn't want a run rejected on uncertain grounds.