From e13f80cd8865513864092b31700ac7fd7dbc05f0 Mon Sep 17 00:00:00 2001 From: Nicole <41876584+NicoleFaye@users.noreply.github.com> Date: Wed, 16 Apr 2025 12:59:26 -0700 Subject: [PATCH 1/4] fix coordinate system interpretation --- .../plugins/game_wrapper_pokemon_pinball.pxd | 8 ++--- pyboy/plugins/game_wrapper_pokemon_pinball.py | 29 ++++++++++++---- pyboy/utils.py | 33 +++++++++++++++++++ 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_pinball.pxd b/pyboy/plugins/game_wrapper_pokemon_pinball.pxd index 75991a3b9..78d02d5af 100644 --- a/pyboy/plugins/game_wrapper_pokemon_pinball.pxd +++ b/pyboy/plugins/game_wrapper_pokemon_pinball.pxd @@ -10,10 +10,10 @@ cdef class GameWrapperPokemonPinball(PyBoyGameWrapper): cdef readonly int ball_saver_seconds_left cdef readonly int ball_size cdef readonly int ball_type - cdef readonly int ball_x - cdef readonly int ball_x_velocity - cdef readonly int ball_y - cdef readonly int ball_y_velocity + cdef readonly float ball_x + cdef readonly float ball_x_velocity + cdef readonly float ball_y + cdef readonly float ball_y_velocity cdef readonly int balls_left cdef readonly int current_map cdef readonly int current_stage diff --git a/pyboy/plugins/game_wrapper_pokemon_pinball.py b/pyboy/plugins/game_wrapper_pokemon_pinball.py index 8208ad88c..24f9bd171 100644 --- a/pyboy/plugins/game_wrapper_pokemon_pinball.py +++ b/pyboy/plugins/game_wrapper_pokemon_pinball.py @@ -12,7 +12,7 @@ import logging from enum import Enum -from pyboy.utils import PyBoyException, WindowEvent, bcd_to_dec +from pyboy.utils import PyBoyException, WindowEvent, bcd_to_dec, fixed_point_to_value from .base_plugin import PyBoyGameWrapper @@ -695,11 +695,28 @@ def post_tick(self): self.multiplier = self.pyboy.memory[ADDR_MULTIPLIER] self.ball_size = self.pyboy.memory[ADDR_BALL_SIZE] - - self.ball_x = self.pyboy.memory[ADDR_BALL_X] - self.ball_y = self.pyboy.memory[ADDR_BALL_Y] - self.ball_x_velocity = self.pyboy.memory[ADDR_BALL_X_VELOCITY] - self.ball_y_velocity = self.pyboy.memory[ADDR_BALL_Y_VELOCITY] + self.ball_x = fixed_point_to_value( + self.pyboy.memory[ADDR_BALL_X:ADDR_BALL_X+2], + num_bytes=2, + is_signed=True + ) + self.ball_y = fixed_point_to_value( + self.pyboy.memory[ADDR_BALL_Y:ADDR_BALL_Y+2], + num_bytes=2, + is_signed=True + ) + + # Velocity values (likely signed since they can be negative) + self.ball_x_velocity = fixed_point_to_value( + self.pyboy.memory[ADDR_BALL_X_VELOCITY:ADDR_BALL_X_VELOCITY+2], + num_bytes=2, + is_signed=True + ) + self.ball_y_velocity = fixed_point_to_value( + self.pyboy.memory[ADDR_BALL_Y_VELOCITY:ADDR_BALL_Y_VELOCITY+2], + num_bytes=2, + is_signed=True + ) self.pikachu_saver_charge = self.pyboy.memory[ADDR_PIKACHU_SAVER_CHARGE] diff --git a/pyboy/utils.py b/pyboy/utils.py index a1313a1a0..c6c5cf469 100644 --- a/pyboy/utils.py +++ b/pyboy/utils.py @@ -488,3 +488,36 @@ def bcd_to_dec(value, byte_width=1, byteorder="little"): multiplier *= 100 return decimal_value + +def fixed_point_to_value(raw_bytes, num_bytes=2, is_signed=False, fractional_bits=8): + """ + Convert fixed-point bytes to appropriate value + + Args: + raw_bytes: Byte array containing the fixed-point value + num_bytes: Number of bytes in the value (default: 2 for 16-bit) + is_signed: Whether to interpret as signed (two's complement) + fractional_bits: Number of bits used for the fractional part + + Returns: + A float value representing the fixed-point number + """ + value = int.from_bytes(raw_bytes, "little") + + total_bits = num_bytes * 8 + + # Calculate integer and fractional parts + integer_part = value >> fractional_bits + fractional_part = value & ((1 << fractional_bits) - 1) + + # Handle two's complement for signed values + if is_signed and (value & (1 << (total_bits - 1))): + # It's a negative value in two's complement + # Calculate the negative value properly + integer_value = value + if integer_value & (1 << (total_bits - 1)): + integer_value = -((~integer_value + 1) & ((1 << total_bits) - 1)) + return integer_value / (1 << fractional_bits) + + # Return the full fixed-point value + return integer_part + (fractional_part / (1 << fractional_bits)) \ No newline at end of file From 001cc8f101af98fb074636e8b5a73491907c201c Mon Sep 17 00:00:00 2001 From: Nicole <41876584+NicoleFaye@users.noreply.github.com> Date: Thu, 17 Apr 2025 09:54:48 -0700 Subject: [PATCH 2/4] remove unneeded len param --- pyboy/utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyboy/utils.py b/pyboy/utils.py index c6c5cf469..78b5d8d7e 100644 --- a/pyboy/utils.py +++ b/pyboy/utils.py @@ -489,13 +489,12 @@ def bcd_to_dec(value, byte_width=1, byteorder="little"): return decimal_value -def fixed_point_to_value(raw_bytes, num_bytes=2, is_signed=False, fractional_bits=8): +def fixed_point_to_value(raw_bytes, is_signed=False, fractional_bits=8): """ Convert fixed-point bytes to appropriate value Args: raw_bytes: Byte array containing the fixed-point value - num_bytes: Number of bytes in the value (default: 2 for 16-bit) is_signed: Whether to interpret as signed (two's complement) fractional_bits: Number of bits used for the fractional part @@ -504,7 +503,7 @@ def fixed_point_to_value(raw_bytes, num_bytes=2, is_signed=False, fractional_bit """ value = int.from_bytes(raw_bytes, "little") - total_bits = num_bytes * 8 + total_bits = len(raw_bytes) * 8 # Calculate integer and fractional parts integer_part = value >> fractional_bits From acc99e29a0248e2831e81165e445c13e675b1429 Mon Sep 17 00:00:00 2001 From: Nicole <41876584+NicoleFaye@users.noreply.github.com> Date: Thu, 17 Apr 2025 09:57:05 -0700 Subject: [PATCH 3/4] remove old param --- pyboy/plugins/game_wrapper_pokemon_pinball.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_pinball.py b/pyboy/plugins/game_wrapper_pokemon_pinball.py index 24f9bd171..f65be04e9 100644 --- a/pyboy/plugins/game_wrapper_pokemon_pinball.py +++ b/pyboy/plugins/game_wrapper_pokemon_pinball.py @@ -709,12 +709,10 @@ def post_tick(self): # Velocity values (likely signed since they can be negative) self.ball_x_velocity = fixed_point_to_value( self.pyboy.memory[ADDR_BALL_X_VELOCITY:ADDR_BALL_X_VELOCITY+2], - num_bytes=2, is_signed=True ) self.ball_y_velocity = fixed_point_to_value( self.pyboy.memory[ADDR_BALL_Y_VELOCITY:ADDR_BALL_Y_VELOCITY+2], - num_bytes=2, is_signed=True ) From 1e10a47b93b51ed1f78e9c2a899f268f7ea945d5 Mon Sep 17 00:00:00 2001 From: Nicole <41876584+NicoleFaye@users.noreply.github.com> Date: Thu, 17 Apr 2025 11:13:31 -0700 Subject: [PATCH 4/4] remove extra params --- pyboy/plugins/game_wrapper_pokemon_pinball.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyboy/plugins/game_wrapper_pokemon_pinball.py b/pyboy/plugins/game_wrapper_pokemon_pinball.py index f65be04e9..1d7390271 100644 --- a/pyboy/plugins/game_wrapper_pokemon_pinball.py +++ b/pyboy/plugins/game_wrapper_pokemon_pinball.py @@ -697,12 +697,10 @@ def post_tick(self): self.ball_size = self.pyboy.memory[ADDR_BALL_SIZE] self.ball_x = fixed_point_to_value( self.pyboy.memory[ADDR_BALL_X:ADDR_BALL_X+2], - num_bytes=2, is_signed=True ) self.ball_y = fixed_point_to_value( self.pyboy.memory[ADDR_BALL_Y:ADDR_BALL_Y+2], - num_bytes=2, is_signed=True )