Baekalfen / PyBoy

Game Boy emulator written in Python
Other
4.57k stars 471 forks source link

Input always changes on same scanline #116

Open MineRobber9000 opened 4 years ago

MineRobber9000 commented 4 years ago

A program can tell that it's running on PyBoy because the buttons always change right at vblank.

To reproduce:

  1. Install PyBoy
  2. Start the test ROM "Telling LYs?" (which I have precompiled for your convenience here)
  3. Press all 8 buttons in any order
  4. Watch the arrow sprite at the right side

Expect: Arrow moves after each press, followed by "Pass", as on a real GameBoy

Actual: Arrow stays at upper right of the screen, followed by an "Incorrect behavior" message that clearly isn't "Pass", as below:

tellinglys

The Game Boy emulator BGB by beware passes this test. Normally it changes the input on the first scanline of vertical blanking to reduce input latency. But if a program reads input multiple times during a frame, the emulator starts to randomize on which scanline the input changes. This way, the program can't discern that it's being emulated and freeze on a copy protection screen, but it adds one frame of lag. Once the program returns to polling once a frame, BGB returns to the low-latency behavior.

Related forum topic: https://forums.nesdev.com/viewtopic.php?f=20&t=18026

Baekalfen commented 4 years ago

Haha, that's a clever one. Did any game implement this type of copy protection?

I'll see if we can add it in an easy way

pinobatch commented 4 years ago

I, the author of Telling LYs, am not aware of any games that use lack of keypress time entropy as copy protection. But adding such entropy would improve the quality of a random number generator that needs to be up and running quickly. Applications include shuffling and dealing cards in a solitaire game, choosing the first few pieces in the NEXT area in a falling block game, or creating the map in a search game or roguelike.

If you plan on supporting Super Game Boy, the pattern is different on that platform. Because the SGB system software polls input on Super NES vblank (which is slower than GB vblank), repeated presses appear as an arrow creeping down the side of the screen.

Baekalfen commented 4 years ago

It might be possible through the SDL events to get the specific time an event was triggered, and then place it into the game at the right time.

https://wiki.libsdl.org/SDL_KeyboardEvent

krs013 commented 4 years ago

Perhaps we could have the input work differently depending on whether the speed is limited. If the game is running at 1x or 2x or whatever, check the input at each scanline like the hardware does, and if there’s no speed limit just submit it at the v blank like we currently do.