This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Fix AttributeError: _framebuffer_copy_detailed_count
Summary
Fixed aAttributeErrorwhat happened during execution when the code tried to access the attribute_framebuffer_copy_detailed_countwhich was not initialized in the classViboy. The error occurred
in the methodrun()when trying to verify the counter before initializing it. Added initialization
of the counter using the patternhasattr()before using it, following the same convention as other similar counters
in the code.
Hardware Concept
This fix is not directly related to the Game Boy hardware, but rather to state management in the emulator. However, it is important to understand that diagnostic counters are useful tools for tracking behavior. of the emulator without affecting the performance of the main loop.
Lazy Attribute Initialization in Python
In Python, it is common to use the "lazy initialization" pattern for attributes that are only needed under certain conditions. This pattern consists of:
- Check if the attribute exists using
hasattr() - Initialize it only if it does not exist
- Use it normally after verification
This pattern is useful when:
- The attribute is only needed under certain conditions (e.g. when debug mode is activated)
- You want to avoid initializing many attributes in the constructor if they are not going to be used
- Need to maintain compatibility with code that may or may not initialize the attribute
Implementation
Identified Problem
During execution, the following error occurred:
AttributeError: 'Viboy' object has no attribute '_framebuffer_copy_detailed_count'
File "/media/fabini/8CD1-4C30/ViboyColor/src/viboy.py", line 1018, in run
if self._framebuffer_copy_detailed_count<= 5:
The code was trying to access the attribute_framebuffer_copy_detailed_countwithout first checking if it existed,
causing aAttributeErrorwhen the attribute was not initialized.
Implemented Solution
Added counter initialization using patternhasattr()before using it, following the same
convention than other similar counters in the code (such as_framebuffer_copy_verify_count).
Code Before (Incorrect)
#4. Check first 20 pixels after copying
first_20_after = [fb_data[i] & 0x03 for i in range(min(20, len(fb_data)))]
if self._framebuffer_copy_detailed_count<= 5: # ❌ AttributeError si no existe
logger.info(f"[Viboy-Framebuffer-Copy-Detailed] First 20 indices after copy: {first_20_after}")
Code After (Correct)
#4. Check first 20 pixels after copying
first_20_after = [fb_data[i] & 0x03 for i in range(min(20, len(fb_data)))]
# Initialize counter if it does not exist
if not hasattr(self, '_framebuffer_copy_detailed_count'):
self._framebuffer_copy_detailed_count = 0
if self._framebuffer_copy_detailed_count<= 5:
self._framebuffer_copy_detailed_count += 1
logger.info(f"[Viboy-Framebuffer-Copy-Detailed] First 20 indices after copy: {first_20_after}")
Fixed Locations
Added initialization in two places where the counter is used:
- Line ~1018:Before checking the first 20 pixels after copying
- Line ~1065:Before counting indexes in the copy (redundant initialization for security)
Affected Files
src/viboy.py- Added initialization_framebuffer_copy_detailed_countin two places (lines ~1018-1020 and ~1065-1067)
Tests and Verification
A quick test was run to verify that the bug was fixed:
Command Executed
timeout 5 python3 main.py roms/tetris.gb 2>&1 | grep -E "(Error|AttributeError|_framebuffer_copy_detailed_count)"
Result
✅ The error ofAttributeError: 'Viboy' object has no attribute '_framebuffer_copy_detailed_count'it no longer appears.
The code now initializes the counter correctly before using it, following the same pattern as other diagnostic counters in the code.
Sources consulted
- Python Documentation:hasattr()- Function to check if an object has an attribute
- Python Best Practices: Lazy attribute initialization
Educational Integrity
What I Understand Now
- Lazy initialization:It is a useful pattern for attributes that are only needed under certain conditions, avoiding initializing many attributes in the constructor
- hasattr():Allows you to check if an object has an attribute before accessing it, avoiding AttributeError
- Code consistency:It is important to follow the same pattern as other similar counters in the code to maintain consistency
What remains to be confirmed
- Initialization in __init__:Consider whether it would be better to initialize all diagnostic counters in the constructor to avoid these types of errors
Hypotheses and Assumptions
Assumption:Lazy initialization is preferable for diagnostic counters that are only used in debug mode, since it avoids initializing many unnecessary attributes when debug mode is disabled. This assumption is supported by the fact that other similar counters in the code use the same pattern.
Next Steps
- [ ] Consider initializing all diagnostic counters in the constructor to avoid similar errors
- [ ] Verify that there are no other attributes that may have the same problem
- [ ] Continue with rendering tests after correcting Step 0366