Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/nutcracker/sputm/windex_v6.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ def __repr__(self):
'or': 11,
}

ARITH_OPS = frozenset('+-*/%') # self-parenthesize so each formula is one token


class BinExpr:
def __init__(self, op, left, right):
Expand Down Expand Up @@ -204,6 +206,7 @@ def __repr__(self):
or isinstance(left, Negate)
or (
isinstance(left, BinExpr)
and left.op not in ARITH_OPS
and left.pre >= self.pre
and left.op != self.op
)
Expand All @@ -215,11 +218,14 @@ def __repr__(self):
or isinstance(right, Negate)
or (
isinstance(right, BinExpr)
and right.op not in ARITH_OPS
and right.pre >= self.pre
and right.op != self.op
)
):
right = f'({right})'
if self.op in ARITH_OPS:
return f'({left} {self.op} {right})'
return f'{left} {self.op} {right}'


Expand Down Expand Up @@ -2406,9 +2412,10 @@ def o6_cursorCommand(op, stack, game):
if game.he_version >= 70 or game.version >= 7:
# TODO: Figure out object?
return f'cursor {stack.pop()}'
# TODO: another pop for non HE or HE < 70 games
image = stack.pop()
return f'cursor {stack.pop()} image {image}'
# Non-HE / HE<70 (v6): setCursorFromImg(obj, room). ScummVM popRoomAndObj pops
# room first, then obj; emit obj first so this reads 'cursor image <obj> room <room>'.
room = stack.pop()
return f'cursor image {stack.pop()} room {room}'
elif cmd.num == 0x9A:
ypos = stack.pop()
xpos = stack.pop()
Expand Down Expand Up @@ -5799,6 +5806,10 @@ def decompile_script(elem, game, verbose=False, transform=True):
asts = deque()
res = None

# Stack state tracking for proper control flow handling
# Maps jump target addresses to saved stack states
saved_stacks = {}

# # clear local variables:
# for key in g_vars: # NOTE: dict key is tuple, we iterates on keys only
# _, var = key
Expand Down Expand Up @@ -5840,6 +5851,7 @@ def decompile_script(elem, game, verbose=False, transform=True):
yield f'\tverb {entries[off + 8]} {{'
indent = 2 * '\t'
stack.clear()
saved_stacks.clear()
if verbose:
yield ' '.join(
[
Expand All @@ -5850,6 +5862,11 @@ def decompile_script(elem, game, verbose=False, transform=True):
)
if isinstance(res, ConditionalJump) or isinstance(res, UnconditionalJump):
srefs.add(off)

# Restore saved stack state at jump targets
if off in saved_stacks:
stack = deque(saved_stacks[off])

stack_backup = list(stack)
try:
res = ops.get(stat.name, defop)(stat, stack, game)
Expand All @@ -5870,6 +5887,12 @@ def decompile_script(elem, game, verbose=False, transform=True):
# # '\t\t\t\t',
# # defop(stat, stack, bytecode),
# )

# Save stack state for jump targets
if isinstance(res, (ConditionalJump, UnconditionalJump)):
target = res.ref.abs
if target not in saved_stacks:
saved_stacks[target] = list(stack)
yield from print_locals(indent)
l_vars.clear()
yield from print_asts(
Expand Down