⚠️ Clean-Room / Educational

This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.

Test: Auto-Press Start to Unlock

Date:2025-12-18 StepID:0077 State: draft

Summary

Added an experimental test of automatically pressing the Start button after 2 seconds of running to try to unlock the game that is frozen on the Game Freak logo. The hypothesis is that many games wait on logo screens until the user presses a button, and if the emulator does not simulate this input, the game freezes.

This is a diagnostic test, not a final implementation. If it works, it will confirm that the problem is lack of user input. If it doesn't work, it will indicate that there is a deeper bug in the CPU or interrupt handling.

Hardware Concept

Many Game Boy games display the logo of the developer or manufacturer and wait until the user presses a button (usually Start or A) or until a certain time passes (managed by V-Blanks).

The Game Boy Joypad works with Active Low logic: when a button is pressed, its corresponding bit in register P1 (0xFF00) is set to 0. When this transition (from released to pressed) is detected, a Joypad interrupt (IF Bit 4, 0xFF0F) with vector 0x0060 is requested.

If the game is waiting for a button press to advance, but the user never presses anything (or the emulator does not simulate this input), the game is stuck in a waiting loop.

Diagnostic hypothesis:If the game is in a loop waiting for input from the Joypad, simulating a Start press after 2 seconds should unlock the game and allow it to progress. If it doesn't work, the problem is somewhere else (CPU, interrupts, etc.).

Source: Pan Docs - Joypad Input

Implementation

Added logic in the methodrun()ofsrc/viboy.pyto simulate an automatic press of the Start button after 2 seconds of execution, and releasing it 0.2 seconds later.

Changes made

Two variables were added to the start of the main loop:

  • start_time: Execution start time (usingtime.time())
  • auto_start_pressed: Flag to track if Start has already been pressed (avoid multiple presses)

Inside the main loop, the following logic was added:

# TEST: Auto-press Start after 2 seconds
current_time = time.time()
if not auto_start_pressed and current_time - start_time > 2.0:
    logger.info("🤖 AUTO-PRESS: Pressing START to unlock...")
    if self._joypad is not None:
        self._joypad.press("start")
    auto_start_pressed = True
if auto_start_pressed and current_time - start_time > 2.2:
    if self._joypad is not None:
        self._joypad.release("start")

This makes:

  • After 2 seconds: Start is pressed automatically and a message is displayed in the log.
  • At 2.2 seconds: Start is released.
  • The press only happens once (controlled byauto_start_pressed).

The methodpress()of the Joypad now handles correctly:

  • Detect the transition from released to pressed.
  • Request Joypad interrupt (IF Bit 4) when a button is pressed.
  • Action logging.

Affected Files

  • src/viboy.py- Added Start auto-press logic after 2 seconds in the methodrun()
  • docs/bitacora/entries/2025-12-18__0077__test-auto-press-start-unlock.html- New log entry
  • docs/bitacora/index.html- Updated with new entry
  • docs/bitacora/entries/2025-12-18__0076__diagnosis-timer-tac-interruptions.html- Updated "Next" link
  • COMPLETE_REPORT.md- Added step entry 0077

Tests and Verification

This is an experimental diagnostic test. The verification will be carried out by running the game and observing if it advances after automatically pressing Start.

  • Execute command: python main.py pkmn.gb
  • Around:Windows/Python 3.10+
  • What to look for in the logs:
    • 🤖 AUTO-PRESS: Pressing START to unlock...: Confirms that the automatic press was executed.
    • Joypad: Interrupt requested by 'start': Confirms that Joypad interrupt was requested.
    • If the game progresses after 2 seconds: The test is successful, the problem was lack of user input.
    • If the game still freezes: The problem is somewhere else (CPU, interruptions, etc.).

State:Pending execution and observation.

Note:This is a diagnostic test, not a final solution. If it works, you could consider implementing a configuration option to allow/disable this behavior, or simply document that the user must press Start manually.

Sources consulted

Educational Integrity

What I Understand Now

  • Logo Screens:Many games stay on logo screens waiting for user input or a set amount of time before advancing to the main menu.
  • Joypad Interruption:When a button is pressed, a Joypad interrupt (IF Bit 4) with vector 0x0060 is requested. If the game is waiting for this interruption, it will not progress until it occurs.
  • Systematic diagnosis:By simulating a Start press automatically, we can determine if the problem is a lack of user input or a deeper CPU/interrupt bug.

What remains to be confirmed

  • Is the game waiting for input from the Joypad?We need to run the game and see if it progresses after the automatic Start press.
  • Does the Joypad interrupt fire correctly?We need to verify that the log shows the requested interruption.
  • Is there a bug in Joypad interrupt handling?If the tap does not unlock the game, there may be an issue in how the interrupt is handled.

Hypotheses and Assumptions

Main hypothesis:The game freezes because it is waiting for a button press that never comes. Simulating a Start press should unlock the game.

Assumption:The Joypad implementation and Joypad interrupt are correct. If auto-clicking doesn't work, the problem is somewhere else (infinite loop in CPU, interrupt handling bug, etc.).

Next Steps

  • [ ] Executepython main.py pkmn.gband observe if the game advances after 2 seconds
  • [ ] Verify that the message appears🤖 AUTO-PRESS: Pressing START to unlock...in the logs
  • [ ] If it works: Confirm that the problem was a lack of user input. Consider implementing a configuration option or documenting expected behavior.
  • [ ] If it doesn't work: Continue the diagnosis in other directions (CPU, interrupts, etc.). The problem is not a lack of user input.