Jump to content

Photo

Emulation and RSYNC?


9 replies to this topic

#1 jmchacon OFFLINE  

jmchacon

    Combat Commando

  • 7 posts

Posted Sun Jun 3, 2018 6:11 PM

I've been working on a 2600 emulator (yes, I know about Stella but this was so I could do easier integration with other potential projects).

 

I have HMOVE and all it's oddities working as best as I can tell but I'm a bit unsure on RSYNC. Looking at the schematics it appears to just force the main counter into the reset state (after 3-6 clocks depending where H1/H2 timing is at). 

 

So happening mid-scan line would potentially give another full set of pixel clocks to work with? i.e. triggering right at the end of HBLANK in theory would restart and give another 21-22 cpu clocks or so before painting occurs? The schematic looks like it's a normal reset of everything so it asserts resetting the HSYNC and disabling the beam, etc.

 

I read through some commented space invaders code and it's used twice there. Once right after WSYNC and another it looks like as I described above (trigger WSYNC, compute a few things and then RSYNC to recover clocks).

 

This isn't super well documented that I've found so until my Harmony cart arrives and I can write some test code I'm mostly stuck at interpreting 40 year old schematics :)

 

James

 



#2 jmchacon OFFLINE  

jmchacon

    Combat Commando

  • Topic Starter
  • 7 posts

Posted Sun Jun 3, 2018 11:43 PM

On 2nd thought HSYNC always vertically advances the beam.....So hitting RSYNC mid line should persist the previous pixels not yet painted this time (due to CRT effects) and then start the next line. So assuming one did this only every few frames shouldn't see flicker/fade.

 

If it was done every frame for a specific set of lines then on a CRT those would slowly fade back out I think. Anyone know of a game that did this?



#3 DirtyHairy OFFLINE  

DirtyHairy

    Moonsweeper

  • 399 posts
  • Location:Germany

Posted Mon Jun 4, 2018 5:26 AM

From looking at your source, you are emulating the VCS from reverse engineering the schematics --- an interesting approach :) I am looking forward to the outcome. I am the author of the TIA emulation in Stella 5 and 6502.ts (they share the same core). A few thoughts:

  • There is a very interesting analysis of the TIA schematics by Andrew Towers here: TIA Hardware Notes This formed the basis of my implementation and was enough to get flawless emulation of 90% of the games out there. There are a few more idosyncrasies (e.g. positioning in the last few cycles of hblank) that I could only get correct via trial and error; it would be interesting if your approach could explain those from first principles
  • If you are reading the Stella source, you might (!) find the 6502.ts source (https://github.com/6502ts/6502.ts) easier to read --- it is Typescript and, as it is much younger, has much less noise in it.
  • The nocash description of the VCS that you quote in your blog is a pretty dangerous resource, there is a lot of interpretation in it, and some parts are just plain wrong.
  • If you browse the Stella bug tracker on GitHub, you can find lots of issues from the last 1.5 years that refer to edge cases in the new TIA core. Most of them have testcases attached as well.
  • RSYNC is handled by the new core by setting the line counter to color clock 225, which effectively resets the counter (and terminates the line) after three more clocks. From the top of my head, I'm not sure where the 225 comes from, I guess it is the result of trial and error. Again, there is a (closed) Stella bug that has more information, including several test cases. There is also a thread somewhere here that contains the initial research on RSYNC several years ago.
  • I think most games that use RSYNC don't actually do so on purpose :) The only game I know that actually uses RSYNC in a meaningful way is "Extra Terrestials"

 

EDIT: The 225 comes from AT's notes I think, no trial'n'error ;)


Edited by DirtyHairy, Mon Jun 4, 2018 6:54 AM.


#4 jmchacon OFFLINE  

jmchacon

    Combat Commando

  • Topic Starter
  • 7 posts

Posted Mon Jun 4, 2018 8:49 AM

I've read the Tower notes extensively since they are effectively a jump start on staring at schematics. The NMOS logic of the era is "interesting" to interpret :) He's got some oddities in clock references in places so one has to be careful to use CPU vs pixel vs the x4 counter when interpreting sometimes.

 

Definitely will take a look at the typescript version. The C++ parts were a bit obtuse in places I'll admit. I'm also trying to avoid referencing other emulations if possible to greenfield this but sometimes there's only so much I can infer on my own it seems.

 

I've really learned which write-ups are bad. I think the one you mentioned I mostly use a cross reference for some specs. I agree it's not great and obviously wrong in places. Thankfully the schematics tend to win out when I'm confused.

 

225 makes sense since RSYNC has to go through an H1/H2 cycle before it works since it just feeds into the same circuit as normal end of line does (i.e. when the H counter reaches it's end). I ended up processing the H1/H2 cycles and then forcing my counter to end of line.

 

Since I'm pretty sure my current implementation is close to the hardware I wrote a quick test to check persistence and got a surprise. I forgot this only resets the Hclock and nothing else. That means it immediately skews the sprite clocks by whatever amount of visible area was in play. I was painting the ball down the middle of the screen and RSYNC in the middle of that which threw it all over the place on the next line since it picks up painting at the left edge. I need to debug a bit more but for once I feel like these are expected side effects :)

 

From looking at your source, you are emulating the VCS from reverse engineering the schematics --- an interesting approach :) I am looking forward to the outcome. I am the author of the TIA emulation in Stella 5 and 6502.ts (they share the same core). A few thoughts:

  • There is a very interesting analysis of the TIA schematics by Andrew Towers here: TIA Hardware Notes This formed the basis of my implementation and was enough to get flawless emulation of 90% of the games out there. There are a few more idosyncrasies (e.g. positioning in the last few cycles of hblank) that I could only get correct via trial and error; it would be interesting if your approach could explain those from first principles
  • If you are reading the Stella source, you might (!) find the 6502.ts source (https://github.com/6502ts/6502.ts) easier to read --- it is Typescript and, as it is much younger, has much less noise in it.
  • The nocash description of the VCS that you quote in your blog is a pretty dangerous resource, there is a lot of interpretation in it, and some parts are just plain wrong.
  • If you browse the Stella bug tracker on GitHub, you can find lots of issues from the last 1.5 years that refer to edge cases in the new TIA core. Most of them have testcases attached as well.
  • RSYNC is handled by the new core by setting the line counter to color clock 225, which effectively resets the counter (and terminates the line) after three more clocks. From the top of my head, I'm not sure where the 225 comes from, I guess it is the result of trial and error. Again, there is a (closed) Stella bug that has more information, including several test cases. There is also a thread somewhere here that contains the initial research on RSYNC several years ago.
  • I think most games that use RSYNC don't actually do so on purpose :) The only game I know that actually uses RSYNC in a meaningful way is "Extra Terrestials"

 

EDIT: The 225 comes from AT's notes I think, no trial'n'error ;)



#5 stephena OFFLINE  

stephena

    River Patroller

  • 3,132 posts
  • Stella maintainer
  • Location:Newfoundland, Canada

Posted Mon Jun 4, 2018 9:11 AM

Definitely will take a look at the typescript version. The C++ parts were a bit obtuse in places I'll admit.

 

I have tried over the years to keep the C++ code clean and well commented.  I've even received feedback over the years that this project is one of the better commented ones out there.

 

It would be beneficial if you would point out the 'obtuse' parts of the codebase, since you have twice now implied that the code isn't great, but still don't point out exactly how or why.  If you're not familiar with modern C++11 code it will seem a little overwhelming, but we can't improve it if you don't give constructive criticism how where it can be improved.  Giving statements like "while very good doesn't have the best source code in places" and "C++ parts were a bit obtuse in places" without backing it up seems more like disparagement than constructive criticism.

 

Also not clear on where you say "the C++ parts".  The entire codebase is C++, so if the "C++ parts are obtuse", I guess you mean the entire codebase is obtuse.



#6 jmchacon OFFLINE  

jmchacon

    Combat Commando

  • Topic Starter
  • 7 posts

Posted Mon Jun 4, 2018 11:27 AM

Sorry if I was coming across too opinionated there. Diving in randomly I ended up in Ball.cxx for instance and there's very few comments and a lot of magic constants. Same with a few other files I looked at while trying to pick some specifics. It's not impenetrable but without a lot of context it's not the simplest to follow initially either.

 

Not saying the code isn't good (it's very well done C++) but as someone diving in to a specific portion there is a dearth of comments in the tia code I was reading. Code back in the main emucore may be better but I was concentrating in the tia directory at the time.

 

I'll make an update on my other public posts to get more specific as well. Again, sorry if that came off a bit harsh.

 

 

I have tried over the years to keep the C++ code clean and well commented.  I've even received feedback over the years that this project is one of the better commented ones out there.

 

It would be beneficial if you would point out the 'obtuse' parts of the codebase, since you have twice now implied that the code isn't great, but still don't point out exactly how or why.  If you're not familiar with modern C++11 code it will seem a little overwhelming, but we can't improve it if you don't give constructive criticism how where it can be improved.  Giving statements like "while very good doesn't have the best source code in places" and "C++ parts were a bit obtuse in places" without backing it up seems more like disparagement than constructive criticism.

 

Also not clear on where you say "the C++ parts".  The entire codebase is C++, so if the "C++ parts are obtuse", I guess you mean the entire codebase is obtuse.



#7 jmchacon OFFLINE  

jmchacon

    Combat Commando

  • Topic Starter
  • 7 posts

Posted Mon Jun 4, 2018 1:32 PM

I did some more thinking about RSYNC and observed behavior after I wrote a test.

 

Since it completely shifts the clocks (WRT the sprite clocks) this appears to allow sprite movement without an HMOVE/comb but you are restricted based on timing and the 3x difference in pixel vs CPU clocks.

 

Example: I'm drawing a ball in the middle of the screen and then issue an RSYNC. Depending where I hit it I jump about 76 pixel clocks right all of sudden due to the synch change between the 2 clocks. Think of it how the HMOVE comb adds 8 pixels to every sprite and then those have to be recovered during HMOVE due to how the comparators work internally (i.e. a move 0 is really 8 extra clocks of the given sprite to move it left 8 to get a 0 net movement).

 

I'm thinking in addition to allowing a fadeout effect (on a real CRT...not sure how an LCD will handle it emulating the signal) this could be used to do large movements of sprites between lines and some careful timing. It's really coarse but it does allow > 15 pixels which is the best one can do with an HMOVE triggered on pixel 224 (or so).


Edited by jmchacon, Mon Jun 4, 2018 1:33 PM.


#8 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!, Boulder Dash, THREE·S, Star Castle

  • 23,277 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany, Europe, Earth

Posted Mon Jun 4, 2018 1:42 PM

  • RSYNC is handled by the new core by setting the line counter to color clock 225, which effectively resets the counter (and terminates the line) after three more clocks. From the top of my head, I'm not sure where the 225 comes from, I guess it is the result of trial and error. 

EDIT: The 225 comes from AT's notes I think, no trial'n'error ;)

225+3 == 76 * 3



#9 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!, Boulder Dash, THREE·S, Star Castle

  • 23,277 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany, Europe, Earth

Posted Mon Jun 4, 2018 1:45 PM

Sorry if I was coming across too opinionated there. Diving in randomly I ended up in Ball.cxx for instance and there's very few comments and a lot of magic constants.

That's the new TIA core which has an open issue (for DirtyHairy) for adding comments. :)



#10 DirtyHairy OFFLINE  

DirtyHairy

    Moonsweeper

  • 399 posts
  • Location:Germany

Posted Mon Jun 4, 2018 2:03 PM

From the effects that you describe, your RSYNC implementation sounds correct. I am not sure about the full H1 / H2 cycle though, that gets me thinking that my implementation in Stella / 6502.ts might be wrong, but I am pretty sure that the testcases we looked at are sensitive to this and would have that covered. I'll have to reinvestigate that at some point ;)

 

Sorry if I was coming across too opinionated there. Diving in randomly I ended up in Ball.cxx for instance and there's very few comments and a lot of magic constants. Same with a few other files I looked at while trying to pick some specifics. It's not impenetrable but without a lot of context it's not the simplest to follow initially either.

 

 

That's my domain. The code is not very well documented, I agree (we've got a ticket for that), but I think with or without comments a thorough look at the core and the way it is driven is necessary to really understand how it works. This is the reason why you might find 6502.ts easier to follow, the code is more straightforward and better isolated from the other parts of the emulation, but there are even less comments there :)

 

As for the magic numbers, the issue to me is that defining them as constants won't make them any less magic (they are not connected, even if they have similar values). If you look at how the core works and have read AT's notes, most of them should be pretty clear up to a offset of +-1 which depends subtly on the order in which the various parts of the simulation are executed.

 

That's no excuse for not documenting the code better, but I don't think it is bad style or particularly hard to read, it just lacks documentation and describes the timing of a piece of hardware that has only patchy documentation as well :P No amount of documentation will make that a joyride without investing a lot of brain grease into understanding the core as a whole and, if you go down that rabbit hole, the lack of documentation won't that much of an issue I think.

 

Overall, I think Stephen has done an amazing job keeping this project readable and accessible for new developers even after two decades of development.


Edited by DirtyHairy, Mon Jun 4, 2018 2:03 PM.





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users