Skip to main content

News

Topic: Sphere 6502 emulator (Read 3319 times) previous topic - next topic

Sphere 6502 emulator
I'm working on porting an emulator of the ancient (relatively speaking) 6502 processor from 6502asm.com to run in Sphere. Getting it to draw as it would on the site (without having to worry about flipping buffers) has been a bit of a chore, but I got it mostly working, but I've noticed that it's significantly slower than the website, both compiling and drawing. Because of the upscale and the way it draws to the screen (coloring individual pixels for each draw), I've had to create <scale_width> by <scale_height> surfaces for each pixel and then fill it with a rectangle (surface_obj.rectangle(0,0,fullwidth,fullheight,color). The issue of slow compilation shouldn't (hopefully) be too much of an issue to look into, but do you have any advice for improving drawing? How does Duktape's spead compare with browsers, or could it just be an issue of having to optimize the site's code to work well with minisphere?



EDIT: wow, I just checked, and both the 1.5 and 1.6 engines perform far better than minisphere. Could this be an issue with minisphere's javascript engine, or would you like me to upload the game folder (please don't look at the source, it's incredibly hacky and I'm not proud of it) and have someone here try it in Windows?
  • Last Edit: April 08, 2016, 03:11:18 am by Eggbert

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #1
Duktape is slower than most browsers due to only being interpreted with no JIT.  However in this case it sounds like your bottleneck is rendering related.  Surfaces in minisphere are created in hardware, so that's probably your problem.

If you're working directly with pixels, one thing you can try is set up a Uint32Array instead of a Surface and write your pixels to that.  Then just: `new Image(width, height, u32arr)` and you can blit the image.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #2
Wait a minute, why are you making individual surfaces for solid-color pixels?  You could just use Rectangle() for that...
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #3
Thinking about this now that I've had some sleep and looking at both your screenshot and the source code from 6502asm.com, it looks like your primary limiting factor is vsync.  See that 61 fps on the bottom?  What I'm guessing happens is that you're becoming "tidal locked" by vsync and thus only being able to write 60 pixels per second (less than two lines).  Sphere 1.5 and 1.6 with the standard32 plugin is actually software-rendered, so I'm guessing vsync doesn't come into play.  I'd be curious what gets displayed if you press F11 in Sphere 1.x.  I'd wager it's a lot higher than 60fps. ;)

Try turning off forced vsync in your graphics driver and see what happens.  There's no reason minisphere should be slower than Sphere 1.5.

This is actually one of the primary reasons spherun displays the framerate by default.  It can be very useful information when trying to debug something like this!
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: Sphere 6502 emulator
Reply #4
>Duktape is slower than most browsers due to only being interpreted with no JIT.
Thinking about it, that shouldn't be an issue, since I believe that most 6502s are only 1-2 MHz.

Also, it's been a long time since I regularly worked with Sphere (hence my random disapperances). I forgot about the Rectangle function. I was aware that using surfaces could present lag, but I couldn't think of another way to do it.

It's set to true by default, but I turned off forced vsync (or "Sync to VBlank" as it's called in NVIDIA Settings), and it runs much faster. Still not as fast as the 6502asm.com version (probably because of the surface usage), but if you've looked at some of the stuff on there, it seems to run way too fast, like the helicopter game that can barely respond before you crash.



EDIT: Even with the surface replaced with Rectangle(), it's still very slow. I'm not sure if this is because of poorly optimized code on my part or issues with misplaced FlipScreens, but I'm looking into it now. Just for testing, since 6502asm.com was put up ~10 years ago (according to the header), I'm creating a Windows XP VM with roughly the specs of an average computer then to test the speed.
  • Last Edit: April 08, 2016, 03:26:59 pm by Eggbert

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #5
Hm, it's hard to say without seeing your code.  Duktape is definitely faster by far (at least twice as fast on average) compared to the SpiderMonkey in Sphere 1.5, and probably about on par with 1.6.  With vsync turned off and no SetFrameRate() calls, your only limiting factor for FlipScreen is how fast the hardware can flip the backbuffer.  On modern machines that tends to be north of 2,000 fps in most of my benchmarks.  Now that sounds like a lot, but here's the thing: Your emulated display is 32x32 (= 1K pixels).  If you do a FlipScreen() for every pixel written and fully update the screen every frame, 2,000fps only gets you just south of 2 (!) emulated frames per second.  3,000 fps would net you 3.

Now I'm not sure how Sphere 1.x implements FlipScreen(), but minisphere performs an actual backbuffer flip every time you call it, along with event loop processing, etc.  I think you'll have to limit the number of times you call it.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: Sphere 6502 emulator
Reply #6

>Duktape is slower than most browsers due to only being interpreted with no JIT.
Thinking about it, that shouldn't be an issue, since I believe that most 6502s are only 1-2 MHz.


You may be surprised what it can take for accurate emulation.

It takes well over 2 GHz with Higan (nee bsnes) just to emulate a SNES, and that's using a combination of highly tuned C, C++, and assembly (including some crazy hacks like libco which uses some CPU instructions that no compiler can take advantage of).

On the other hand, for a system with few chips, you can almost always get away with slower languages. There is a GB, GBC, and GBA emulator written in JS that runs acceptably with pretty good accuracy, even on the pre-JIT Firefox versions. If you are mostly worried about a single chip emulation (which is what the GB is, almost entirely) then you will be just fine. Once you start adding other components of the system it may become an issue.

Re: Sphere 6502 emulator
Reply #7
Wow, this is embarrasing. Even on Windows XP, running ye olde Netscape 7, with the execution cap lowered to make the speed more realistic, it's still significantly faster
https://db.tt/jgZZ9lYL

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #8

It takes well over 2 GHz with Higan (nee bsnes) just to emulate a SNES, and that's using a combination of highly tuned C, C++, and assembly (including some crazy hacks like libco which uses some CPU instructions that no compiler can take advantage of).


...why?  This seems excessive.  I've been using SNES emulators since I had an 83MHz Pentium OverDrive (basically a 486 on steroids) and it ran well enough there.  Granted, that was with ZSNES on DOS where there is practically zero overhead from the OS, so we'll use a more fair comparison: Snes9x for Windows.  I've been running that since I had a 500MHz Celeron that could barely run Windows XP, and I don't remember seeing any lag.  The emulation seemed pretty damn accurate, too. What kind of crazy things is Higan emulating that it needs 2+ GHz?
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #9

Wow, this is embarrasing. Even on Windows XP, running ye olde Netscape 7, with the execution cap lowered to make the speed more realistic, it's still significantly faster
https://db.tt/jgZZ9lYL


See my post above.  My suspicion is that you need to cool it on the FlipScreen() calls.  Like I said though, without seeing your code it's hard to know what's wrong.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: Sphere 6502 emulator
Reply #10

On the other hand, for a system with few chips, you can almost always get away with slower languages. There is a GB, GBC, and GBA emulator written in JS that runs acceptably with pretty good accuracy, even on the pre-JIT Firefox versions. If you are mostly worried about a single chip emulation (which is what the GB is, almost entirely) then you will be just fine. Once you start adding other components of the system it may become an issue.

Yeah, I remember I posted a link to that HTML5 GBA emulator. It ran poorly on my old laptop, but it was very much an "economy" laptop.

And I was going to post that the FPS takes a nosedive if the game makes calls to $FF, which holds keypresses, but I just had it run the adventure one, which is one of the most complex ones on the site, and it ran pretty decently.



See my post above.  My suspicion is that you need to cool it on the FlipScreen() calls.  Like I said though, without seeing your code it's hard to know what's wrong.

I'm going to upload my code in just a bit, but how would you normally write to the screen and keep it updated regularly while writing to different pixels, as in this case? The original doesn't use buffers, since because it's drawing to table elements as pixels, it doesn't need to.

Re: Sphere 6502 emulator
Reply #11
Also, my actual FPS doesn't seem to be that bad, even when the CPU screen's is. For example, the skier.asm has horrible FPS, yet it shows the actual FPS at around 1000


Re: Sphere 6502 emulator
Reply #13
@Lord English: That's because ZSNES is not accurate in the slightest, though. Neither is snes9x. They emulate a machine that only somewhat represents an SNES, and happens to work properly with some well known games like Super Mario World and Zelda: LttP. In fact, at one point one of the two (I forget which) shipped with copies of textures of all games that used a certain format, just because they didn't want to (or couldn't) implement some feature that would let them actually load those textures.

Once you actually make accuracy a goal, performance is tricky. The SNES requires sub-cycle precision to emulate the interactions of the coprocessors in it. You can just not do that, and just YOLO it. That's what ZSNES and Snes9x do, and because of it only a handful of games really work properly, and most obscure games simply do not work at all. Higan/bsnes has actually achieved 100% compatibility with all commercial games, and it still isn't truly 100% accurate (some homebrew exists that has different behaviour on hardware as it does on Higan).

There's a balance to be sure, but the accuracy of snes9xand ZSNES is just embarrassing. People tend to accept the poor accuracy, but that doesn't mean that it isn't inaccurate.

My point is that "it shouldn't be hard to emulate a system with a 2MHz CPU" isn't always true. There's a lot more to the performance of an emulator than the clock speeds of the chips.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: Sphere 6502 emulator
Reply #14
@Eggbert:
I did some testing.  Compilation actually seems faster with minisphere compared to Sphere, which is what I expected.  I think a big cause of your slowness there was that you do FlipScreen() after each line compiled to show progress.  With vsync on, you can then only compile 60 lines per second, and since test.asm has 600+, that's 10 full seconds to compile.  With vsync off compilation is pretty much instantaneous.  It's probably better to remove the FlipScreen there.  If you're worried a long compilation will make the OS think minisphere is locked up, replace the FlipScreen() with DoEvents().

All that said, minisphere does seem to perform a bit slower in actually running the compiled code.  So I compared framerates: Sphere 1.5 ran at around 1500fps for me, while minisphere hovered around 1000.  Since you perform a FlipScreen() for every pixel written, that's your limiting factor.  In any case Duktape's performance doesn't seem to have anything to do with it: As I suspected, you're being bottlenecked by rendering.  Thinking about it a bit, I think I know the reason why Sphere 1.x is faster: It uses DirectX, while minisphere uses OpenGL, which tends to get lower framerates on Windows for whatever reason.

The browser version doesn't have the same issue.  It can set pixels in the canvas instantaneously and the browser will worry about actually updating the screen at its own pace.  Sphere is not multithreaded however, so you're going to have to fake it.  What I would do is store the pixel values (which you should already know since you're emulating video memory anyway) and after executing X instructions, render the contents of video memory and call FlipScreen().  If you call SetFrameRate(60) at startup, you can then tweak the speed of the emulated hardware by changing the number of instructions between flips.
  • Last Edit: April 09, 2016, 12:31:52 am by Lord English
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan