22

Some programs notice if they are run on a real Commodore 64 or an emulator. For example, this demo from 2007 stops on VICE emulator 3.2 with the message "No VIC inside". How is this done?

I found some code to identify a Commodore 128 in Commodore 64 mode, but no code to identify emulation.

In particular, I would be interested in a solution to detect a real Commodore 64, THEC64, and VICE emulator in software.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918
Peter B.
  • 4,447
  • 15
  • 36
  • Adding a link to a ziped file without any description doesn't seem like a good idea, does it? – Raffzahn Jan 04 '21 at 23:36
  • 2
    As a case in point, note that this demo (Krestage3) works flawlessly in VICE 3.4 without any "No VIC inside" message. :) – Retrograde Jan 04 '21 at 23:57
  • 2
    Sometimes, the difference is not actually detected, it is just a difference between emulation and real hardware, that makes a message on screen being visible or hidden. It simply means that the emulator does not implement a specific corner case how the real hardware works. – Justme Jan 05 '21 at 07:13
  • According to the definition of program execution (which admits any execution engine that satisfies and implements the specification), you are trying to add a restriction to the engine's specification if you attempt to detect the actual execution engine. I.e. you are trying to work around the basic principle of software development (to depend only on specifications rather than implementations). – Aleksey F. Jan 15 '21 at 23:23
  • @Aleksey I'm not trying to add a restriction but I want to add features to my prgs that make sense with the respective systems. For example, if the system is a THEC64mini, there is no keyboard, so functions need to be mapped onto Joystick functions or Return key. But that is a different topic. – Peter B. Jan 16 '21 at 22:38
  • @PeterB. In this case, there is the need for API to enumerate supported features. And it is up to platform or engine developer rather than app dev. Otherwise, really, the only way is to detect hardware and software environment to determine supported features. Even then, API should be available at least to hardware vendor (ports, interrupts and so on). It is unreliable to depend on feature observations rather than specifications due to vendor does not inform when changes API. So, the only reliable way is to contact vendor or even platform dev: there should be common SDK and API. – Aleksey F. Jan 22 '21 at 02:05
  • @Aleksey I absolutely agree, an API for this would be the best solution. Since the answers so far only hinted at feature observation I'm afraid that there is no API solution so far. But if you are aware of such a feature please feel free to add it as an answer! – Peter B. Jan 22 '21 at 11:03
  • My experience is not relevant to your question (I code for ZX Spectrum), but there is a rich history of hacks of this kind on ZX Spectrum, with some demos even intentionally freezing in emulators. On ZX Spectrum it is usually done via exploration of more esoteric features of the target hardware, esp. certain poorly documented side effects of Z80 commands (e.g. MEMPTR or SCF). Many emulators can also be caught out via timing inconsistencies, e.g. keyboard can change state at any time in ZX Spectrum, but emulators tend to update the state of the keyboard a lot less frequently. – introspec Jul 21 '21 at 13:35

5 Answers5

29

In general, no there is no reliable way to detect an emulator (if it's any good). Especially if it's actively developed.

The trick that worked yesterday probably don't tomorrow as emulation improves. Also, exploiting margins like ghost signals on floating bus lines may just lead to false positives as well, as there were quite a few differences between C64 boards in its life time. (This was a problem with some copy protections based on this scheme, for instance. Also, it could still be emulated if the developer's set their mind to it.)

There's a discussion of the topic over at lemon64 here. As commented, specifically for VICE it may be possible to detect if True Drive emulation is turned off. But the user can still just turn it on.

Earlier versions of VICE supported an emulator ID that was optionally mapped into the memory space to detect the presence but it was since removed.

Retrograde
  • 4,506
  • 1
  • 17
  • 40
  • 1
    Any emulator detection that focuses on the drive will also very probably give a false positive on third party drives, or things like the SD2IEC, even though it's running on a real C-64. – Michael Graf Jan 04 '21 at 22:15
  • Thanks, for the answer. I saw the topic on Lemon64 as well, but unfortunately, they did not come up with practical examples of usable code. While the argument "a good emulator cannot be detected" makes sense, I'm still impressed by some demos (where I forgot the names) doing such a detection. I had True Drive emulation enabled, so it must have been something else. So I think it might be still interesting learning about "yesterdays" (to today's) methods. – Peter B. Jan 04 '21 at 22:17
  • 2
    If you have examples of currently working methods detecting VICE, there's a disassembly challenge ready for taking. :) With a little luck, you can even do it inside the VICE monitor. ;) Time will tell if the next VICE release his picked up the challenge. – Retrograde Jan 04 '21 at 22:21
  • 1
    @Retrograde makes two of us ... that would be areal nifty task:) – Raffzahn Jan 04 '21 at 22:39
12

Wouldn't it defy the purpose of an emulator, designed to mimic a machine as perfect as possible, if it can be detected? In general, every detectable difference must be considered a bug one would expect to be removed ASAP.

Some programs notice if they are run on a real C64 or an emulator.

It would be great if you could add some examples. Especially with notes if these programs do the detection reliably or only in certain configuration/situations.

How is this done?

Assuming that any of the named emulators is good enough to run most C64 software, I would look out for discrepancies in handling of external devices, most likely floppy disk drives. For example, by measuring the response time for various commands send to a drive. Measuring can be done by taking a CIA timer, put in PHI2 counting mode.

Three basic results can be measured:

  • Direct response to a transfer

    (i.e. reaction/round trip times)

  • Response to CPU only commands

    (i.e. answer given by the external device CPU without accessing the drive)

  • Response to positioning and read commands

    (i.e. mechanical response like moving 20 tracks)

Each of this will give indicators about having an unmodified or a modified C64. Modification in this sense can have many meanings

  • Faster drive electronics
  • Faster drives or solid state drives
  • Improved protocol (fastloaders/DOS)
  • Emulator usage

Differences are only gradual, not absolute. A real fast response may come from an emulation that does not care for being as slow in floppy operations as the original (or simply accept the faster operation of the host PC). It may respond almost instant.

But similar results may as well come from a genuine C64 equipped with solid state drives, SD2IEC for example. With increased processing power available such devices may at one point as well deliver instant response with the real C64.

So for sure timing can only reveal relative differences to a genuine setup, not how they are achieved (*1). For this method I would give the response time within a single transmission the highest chance to find something.

I found some code to identify a C128 in C64 mode, but no code to identify emulation.

Detection of a C128 vs. a C64 is a different issue, as these machines do differ in certain details.


*1 - Not to mention that these measurements are only valid within the reference system given, so an emulation delivering the right relative timing may still run faster or slower.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918
  • "Wouldn't it defy the purpose of an emulator, designed to mimic a machine as perfect as possible, if it can be detected?" - Exactly this! – Reversed Engineer Jan 05 '21 at 07:27
  • 4
    "In general every detectable difference must be considered a bug one would expect to be removed ASAP" On x86, it is quite normal for virtualisation (VirtualBox,etc) and emulation platforms (QEMU,Bochs,DOSBox,etc) to expose their identity to the software they are emulating (through DMI data, strings in the BIOS, PCI configuration data, etc). Now, it is generally possible to configure those platforms to hide themselves, but their default configuration is to be open about who they are. I wouldn't call that a bug. But maybe the expectations for C64 emulators are different from those for x86. – Simon Kissane Jan 05 '21 at 10:41
  • Also on the first statement, I’m not 100% on board. E.g. if an emulator is opening a D64 file then only secret contents are specified; there’s quite a lot of leeway in g the exact spacing of what goes around the sector contents, but some authors use hints like that to fingerprint emulators. I don’t know that I’d call it a bug if an emulator always makes the same choices when dealing with a file format that explicitly gives it options. It’s just a side effect of the community’s choice of a lossy file format. – Tommy Jan 05 '21 at 12:19
  • 7
    @SimonKissane Well, exactly, expectations on a C64 are different. The C64 is, unlike the PC, a single definition that didn't change over time. Any difference from that expectation can screw execution of a program. The PC is a way more loose definition. There were not only many different extensions, but manufacturers as well. And the definition changed over time. So for all emulation purpose the C64 must be seen as a game console. – Raffzahn Jan 05 '21 at 12:40
  • @Tommy Not really sure what statement you refer to and what you consider a 'secret content'. Also not sure what the 'bug' reference is supposed to mean. If you read thru, you'll notice that I do as well see interaction with peripherals, with floppy as primary source, see a way to detect emulators. But these differences are as well present in real hardware combinations, even back then. In addition, Some emulators offer 'compatible' timing for drives, making fingerprinting quite hard. – Raffzahn Jan 05 '21 at 12:51
  • Ugh, my phone’s autocorrect has indeed made my earlier comment indecipherable. Apologies. Sector content, not secret content. ‘Bug’ is your term, not mine. And I’m referring to emulators dealing with file formats where variation is permitted in the spec. I don’t think your use of bug applies when an emulator can be detected because it is using in-spec interpretation of a file format A rather than interpretations B–Z. – Tommy Jan 05 '21 at 13:42
  • To try to be more coherent: the mapping from a D64 to a real disk is one to many. Often emulators can be identified by which of the many they pick. I do not think that constitutes a bug. So I disagree with the blanket statement “every detectable difference must be considered a bug”; sometimes they’re because of a flexible spec. – Tommy Jan 05 '21 at 13:49
  • 2
    "Not to mention that these measurements are only valid within the reference system given, so an emulation delivering the right relative timing may still run faster or slower." - for example the drive emulator could give off instant response, but also calculate how long it should take and advance the system clock by that much. – John Dvorak Jan 05 '21 at 13:51
  • @Tommy I see, I guess we have here a misunderstanding. If you read thru the whole answer, not just the first line, you'll notice that I do discuss the ways of possible detection of emulation by timing issues with peripherals. Of course are differences in that area not a bug, after all, they are not part of the C64, but the emulated environment. In addition, as you as well explain, these differences are random and can change at will, so a reliable detection is not possible. Moreso, most of these differences can as well happen with a real C64 setup, thus not even unique to emulation. – Raffzahn Jan 05 '21 at 14:01
  • I'm not talking about the factors you identify, which are primarily around timing, but about much more mundane stuff like how many sync bytes between sectors. That's undefined by file formats like D64, clearly detectable, and I argue not a bug if an emulator doesn't go the extra mile [slightly] to randomise. It'd be more thorough to do so, but it is not a malfunction not to do so. – Tommy Jan 05 '21 at 14:05
  • 1
    @Tommy Aren't these even more about emulation of the drive? Detecting sync bytes only works if the emulator provides a 1541 emulation low enough to even come to that point. So we're again way past the C64 and into characteristics of peripherals - things that already may go different on real machines, so a detection does not always indicate an emulator. – Raffzahn Jan 05 '21 at 14:52
  • @Raffzahn in the sense I'm talking, they're about what the emulator decides is on the physical disk; how the drive and controller react to the disk is further up the stack. But, yeah, I'm certain that many of the demos that announce which emulator they're in are really only doing so probabilistically — the demo scene loves smoke and mirrors. You've persuaded me that I'm saying much the same thing as you though: that an emulator emulates a specific instance of a machine, and often you can detect that instance even if it's one that very well might exist in real life. – Tommy Jan 05 '21 at 15:26
  • 1
    @SimonKissane these virtualization platforms, however, are meant as a productivity/performance/consolidation tool, often used to run state of the art software, not to run software that is completely foreign to the host platform. Optimized to allow separation of stuff with AS LITTLE emulation as possible. – rackandboneman Jan 06 '21 at 18:46
  • @rackandboneman Your point is true for virtualisation platforms such as VirtualBox/VMWare/etc. However, I also mentioned emulators such as Bochs,DOSBox,QEmu which are perfectly capable of emulating x86 on completely alien architectures like ARM, and which also make no attempt (by default) to hide their identity from the subject of emulation. The same is true for the Hercules IBM mainframe emulator. Your point does not hold for these emulators. – Simon Kissane Jan 06 '21 at 22:50
2

One thing that can give emulators away (not reliably, but it might be good enough in practice) is how predictable the results are when you do something that is supposed to yield an undefined result. One thing that comes to mind is what you read from a bus when there is actually nothing writing to it, or using hardware in a way that is known to cause glitches some times but not all the time.

user3840170
  • 23,072
  • 4
  • 91
  • 150
rackandboneman
  • 5,710
  • 18
  • 23
  • You got an example of "what you read from a bus when there is actually nothing writing to it,", like what could that be on a C64. You mean like bits 4-7 of color RAM or something like that? – Omar and Lorraine Jan 06 '21 at 12:14
  • 2
    On 8/16 bit machines with a multiplexed A/D bus, you often actually could read back your address on the data bus (capacitive effect I guess) when reading from an address where physically no memory or I/O device is mapped. Not sure if you can with the C64. – rackandboneman Jan 06 '21 at 13:06
  • But is it really reliably unreliable? – Peter Mortensen Jan 06 '21 at 15:49
  • @rackandboneman: On the 6502, any data fetch which doesn't involve a page crossing, isn't an interrupt-vector fetch, and is outside the range $0x0000-0x01FF, will be preceded by on the bus by MSB of the address. This fact can be handy when doing a custom-cartridge design on the Atari 2600 which doesn't connect the top five address wires on the processor die to anything (they aren't even wired to pins on the package). – supercat Jan 06 '21 at 18:39
  • Disconnected wires like that should either behave like an accidental register, or read back noise. I would not expect an emulator to ... well, emulate whatever the behaviour is in practice, unless explicitly implemented. – rackandboneman Jan 07 '21 at 15:14
2

The only way to detect an emulator that doesn't use emulator ID (all modern ones) is to exploit a difference between that emulator and real hardware. This only works until the emulator gets fixed.

Writing such code is useful only insofar as it helps emulators improve, by providing a test case.

The floating line test has false positives when used to detect emulators. Relying on behavior that is undefined on real hardware is NOT a valid trick. Instead, do tests that are consistent on real hardware, but different on emulators, but realize that the emulator may get fixed. If you can't find one, then you don't need to know it's an emulator.

Demos usually do this because they really push the hardware, and often run into crazy edge cases that the emulator authors haven't implemented yet, and that no one eve expected to even work on a real c64.

0

Most — if not all — CSDB demos expect a PAL C64. VICE or TheC64 (which should be referred to as “Hall of Shame VICE”) typically start up as NTSC.

This demo seems to run adequately in VICE 3.5 for me when invoked with:

x64sc --model pal KRESTAGE3.D64
scruss
  • 21,585
  • 1
  • 45
  • 113