News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: [SNES] I need to detect the host emulator  (Read 2647 times)

gauveldt

  • Jr. Member
  • **
  • Posts: 47
    • View Profile
[SNES] I need to detect the host emulator
« on: April 08, 2014, 10:00:24 am »

I need a way to detect emulators so I can get my audio code to properly adapt to avoid audio buffer underruns and overruns between them.  The problem is they all time slightly different and only bsnes correctly gets that the SPC-700 crystal clocks just slightly slower than the S-CPU and there is enough timing variance that a solution working on one (in bsnes/higan the SPC-700 is on a slightly slower 'crystal' meaning I need to drop frames periodically to avoid overrun but in znses the SPC-700 'crystal' keeps up more closely and the frame dropping leads to underruns making an impossible situation unless I can check between the two and possibly also real hardware to adjust the frame skips accordingly).

d4s had a way to do this but has been made secret by powers that be so whoever has a way to do this please PM me instead of forum posting.

All this secrecy is screwing over the homebrew ROM coding people like myself. :(

Disch

  • Hero Member
  • *****
  • Posts: 2676
  • NES Junkie
    • View Profile
Re: [SNES] I need to detect the host emulator
« Reply #1 on: April 08, 2014, 02:36:39 pm »
If an emulator is doing its job right, it will be indistinguishable from the actual system.

Working emulator-specific hacks into your ROM is a bad idea, IMO.  The "right" way to do this is to get it working on the system.  If it works on an SNES but not in X emulator... then it's X emulator author's responsibility to fix their emulator.  (Give them the ROM, show that it works on the system but not their emu... and most will be happy to fix it).


The bigger problem here is that the SPC clock rate is known to be imprecise and is known to vary from system to system.  So even if you got this working on one SNES, it might not work on another.


Though, why can't you use the SPC itself?  It has 3 timers that are driven by the same clock... so if you have the SPC poll those timers and send back data to the SNES... the SNES can know exactly how much time has passed just by polling the IO regs.

gauveldt

  • Jr. Member
  • **
  • Posts: 47
    • View Profile
Re: [SNES] I need to detect the host emulator
« Reply #2 on: April 08, 2014, 03:42:01 pm »
If an emulator is doing its job right, it will be indistinguishable from the actual system.

Working emulator-specific hacks into your ROM is a bad idea, IMO.  The "right" way to do this is to get it working on the system.  If it works on an SNES but not in X emulator... then it's X emulator author's responsibility to fix their emulator.  (Give them the ROM, show that it works on the system but not their emu... and most will be happy to fix it).


The bigger problem here is that the SPC clock rate is known to be imprecise and is known to vary from system to system.  So even if you got this working on one SNES, it might not work on another.


Though, why can't you use the SPC itself?  It has 3 timers that are driven by the same clock... so if you have the SPC poll those timers and send back data to the SNES... the SNES can know exactly how much time has passed just by polling the IO regs.
The SPC audio streaming code I currently use only makes use of the built-in IPL boot code which has no code otehr than to transfer data into the SPC.  It is a future project to write a custom SPC driver (and figure out exactly which dialect of SPC-700 ASM Asar speaks).

I only have to ever get it so the buffer writes err on the side of being slightly faster and it should be able to go a few hours before incurring an overrun condition in the buffer.

The SPC itself would have benefited from a DSP read-register on each voice for "sample address"  Would have made the SPC driver code to keep audio in sync trivial.

Guess I could count by three for every 64 kHz timer pulse and count a frame (and subtract 8) whenever the count-by-three counter is over 8 and send this count to the SNES.  the snes will keep enough audio so long as it is 8 or more pulses ahead (due that this count method is only stays in sync every 8 pulses for 24 kHz audio)

Disch

  • Hero Member
  • *****
  • Posts: 2676
  • NES Junkie
    • View Profile
Re: [SNES] I need to detect the host emulator
« Reply #3 on: April 08, 2014, 05:20:00 pm »
Quote
The SPC audio streaming code I currently use only makes use of the built-in IPL boot code which has no code otehr than to transfer data into the SPC.  It is a future project to write a custom SPC driver (and figure out exactly which dialect of SPC-700 ASM Asar speaks).

Seems like it'd be easier and just overall better in every way to write a SPC driver than it would be to fill your SNES code with emulator detection and logic forking code.

I don't think there's any way to ensure that the stream will be uninterrupted without feedback from the SPC.  That said... using an SPC timer, it's relatively easy to give the necessary feedback to the SNES.

IMO, using only the IPL Boot ROM is a nice gimmick, but it isn't really practical.  You're unnecessarily crippling yourself.

Quote
The SPC itself would have benefited from a DSP read-register on each voice for "sample address"  Would have made the SPC driver code to keep audio in sync trivial.

I wouldn't say it's necessarily "trivial", but it shouldn't be very difficult to do this on the SPC.  All you have to do is use the timers.

If you have the channel playing at PITCH=$1000, you will go through a 9-byte BRR block every 8*32 cycles.

The slow SPC timers (0 and 1, IIRC) are clocked once every 64 cycles.  So set that target to 4, and the timer counts up every BRR block.

Have an SPC driver poll the timer, multiply it by 9, and write that number back to the IO regs so the SNES knows how many bytes can be written.

Knowing exactly how many bytes can be written = easy to keep in sync.
« Last Edit: April 08, 2014, 05:33:27 pm by Disch »

Nightcrawler

  • Hero Member
  • *****
  • Posts: 5738
    • View Profile
    • Nightcrawler's Translation Corporation
Re: [SNES] I need to detect the host emulator
« Reply #4 on: April 08, 2014, 10:12:31 pm »
On the topic of detecting emulators for whatever purpose, you'd want to attack something that requires the utmost accuracy. In the past many people used reading the multiplication/division registers before they were ready. Many emulators still aren't perfectly correct there. Other ideas used involved precise h/v counter capturing, proper memory map mirroring etc. Then, there there is the differences in initialization. Even BSNES does not match all the intricacies of the hardware. You do have to be careful not to use a variations that actually differ from real SNES to real SNES.

However, I think the point to detecting an emulator though would be to ensure it meets the accuracy level you need. So, you only need to test for the least common denominator that you require to run your software correctly.
TransCorp - Over 20 years of community dedication.
Dual Orb 2, Wozz, Emerald Dragon, Tenshi No Uta, Glory of Heracles IV SFC/SNES Translations

Disch

  • Hero Member
  • *****
  • Posts: 2676
  • NES Junkie
    • View Profile
Re: [SNES] I need to detect the host emulator
« Reply #5 on: April 09, 2014, 10:28:03 am »
Quote
Even BSNES does not match all the intricacies of the hardware. You do have to be careful not to use a variations that actually differ from real SNES to real SNES.

Yeah... this is the real challenge with ROM hacking.  Ideally everyone would be able to test their work on real hardware.  Unfortunately that is difficult/impossible for a lot of people.


Though... looking at this from an emulation standpoint... ROM hacks and homebrews that only work in emulators are actually beneficial because they expose imperfections in emulators.

A classic example is Mario Adventure not knowing about the MMC3 sprite quirk (where all your sprites have to use the same pattern table or the IRQ counter screws up).  At the time, emulators ran it fine.  But after the hack came out and people saw that it didn't work on the system... it got emu authors looking into why... and now new emulators reproduce the true behavior more accurately.

So it's good for emulation, but not necessarily good for the ROM hacker.  Most ROM hackers don't really care about how accurate emulators are as long as their stuff works.

gauveldt

  • Jr. Member
  • **
  • Posts: 47
    • View Profile
Re: [SNES] I need to detect the host emulator
« Reply #6 on: April 09, 2014, 01:52:41 pm »
I added an SPC driver version

April 11, 2014, 01:34:44 am - (Auto Merged - Double Posts are not allowed before 7 days.)
On the topic of detecting emulators for whatever purpose, you'd want to attack something that requires the utmost accuracy. In the past many people used reading the multiplication/division registers before they were ready. Many emulators still aren't perfectly correct there. Other ideas used involved precise h/v counter capturing, proper memory map mirroring etc. Then, there there is the differences in initialization. Even BSNES does not match all the intricacies of the hardware. You do have to be careful not to use a variations that actually differ from real SNES to real SNES.

However, I think the point to detecting an emulator though would be to ensure it meets the accuracy level you need. So, you only need to test for the least common denominator that you require to run your software correctly.

I've already hit two snags in the latest zsnes: the fencepost when storing timer periods counts exclusively.  setting a timer period to 148 clocks 149 cycles before the 4-bit counts up in ZSNES, 148 in higan/bsnes.  This off-by-one causes one emulator or the other to have a buffer fault because the setting to make it work on one breaks the other.  Furthermore in ZSNES the OUTX register (DSP writes a channel's output value to DSP register x9 just before volume adjustment) remains at 0 even when a channel is actively outputting sound and can be heard.  The OUTX I can probably make a check for... detecting the timer's off-by-one not so easy (ask the user?  is audio skipping?  an enable ZSNES hacks option in game's system menu??? [possibly remembering it in SRAM when set]).

Geiger's become completely useless as it just doesn't work right at all now since I switched to using the SPC driver code I wrote.  Mind you I think SA-1 is unsupported in Geiger so I knew it was going to be out eventually anyways which sucks because until byuu releases loki Geiger is the only one that lets you see all memory areas at runtime.  I updated ZSNES with byuu's patch so it would handle full SA-1 (64-bit) banked games [um, Asar, could you please support exhirom 64mbit wihout kludgery, pretty please???]).

AFAIK the big two (excluding Geiger/Snes9X on account of being inop with my ROM) are ZSNES and higan/bsnes.  I could be missing some.

PS:
Anyone release yet a SPCTool that works on 64-bit systems yet?  One that doesn't give "your version of windows is unable to run..." (meaning it is 16/32-bit/DOS app that won't run on 64-bit).  Not that I can really use SPCTool since it has no way to record or playback port inputs from the SNES-side) and of course such would be needed in something like a dynamic player such as streaming audio (same reason ToP's theme is vocal-less when SPC-stated).

Quote
Though... looking at this from an emulation standpoint... ROM hacks and homebrews that only work in emulators are actually beneficial because they expose imperfections in emulators.

As previously stated I already found two (three if I count Geiger not properly working at all).
The bad news is ZSNES is unlikely to be updated to fix them any time soon because the tool chains to build it is non trivial.
Geiger looks to be same poop since it's not being actively updated either.
Everyone's waiting for loki I guess.

Quote
Seems like it'd be easier and just overall better in every way to write a SPC driver than it would be to fill your SNES code with emulator detection and logic forking code.
I did in fact write just such an SPC driver and BAM the fencepost issue on the timer periods is different between ZSNES/higan so it's not possible to have code that works on both without somehow detecting the off-by-one.  The fencepost issue means even the code running on SPC doesn't know if its in sync to the DSP or not!!!
« Last Edit: April 11, 2014, 01:34:44 am by gauveldt »