mirror of
https://github.com/zeldaret/oot.git
synced 2024-12-27 07:07:09 +00:00
127 lines
3.4 KiB
Python
127 lines
3.4 KiB
Python
|
# SPDX-FileCopyrightText: © 2024 ZeldaRET
|
||
|
# SPDX-License-Identifier: CC0-1.0
|
||
|
#
|
||
|
# Misc utilities
|
||
|
#
|
||
|
|
||
|
import struct, subprocess, sys
|
||
|
|
||
|
def debugm(msg):
|
||
|
"""
|
||
|
Debug message on stderr
|
||
|
"""
|
||
|
print(msg, file=sys.stderr)
|
||
|
|
||
|
def error(msg):
|
||
|
"""
|
||
|
Debug message + exit
|
||
|
"""
|
||
|
debugm(msg)
|
||
|
sys.exit(1)
|
||
|
|
||
|
def incbin(rom, offset, size):
|
||
|
return rom[offset:offset+size]
|
||
|
|
||
|
def f32(f):
|
||
|
"""
|
||
|
Reduces precision of f to a 32-bit float for correct intermediate calculations
|
||
|
"""
|
||
|
return struct.unpack("f", struct.pack("f", f))[0]
|
||
|
|
||
|
def u32_to_f32(u):
|
||
|
"""
|
||
|
Convert IEEE-754 binary rep to float
|
||
|
"""
|
||
|
return struct.unpack(">f", struct.pack(">I", u))[0]
|
||
|
|
||
|
def f32_to_u32(f):
|
||
|
"""
|
||
|
Convert float to IEEE-754 binary rep
|
||
|
"""
|
||
|
return struct.unpack(">I", struct.pack(">f", f))[0]
|
||
|
|
||
|
def align(x, n):
|
||
|
"""
|
||
|
Align to next n (power of 2)
|
||
|
"""
|
||
|
return (x + (n - 1)) & ~(n - 1)
|
||
|
|
||
|
def merge_ranges(intervals):
|
||
|
if len(intervals) == 0:
|
||
|
return []
|
||
|
|
||
|
intervals = sorted(intervals, key=lambda x: x[0][0])
|
||
|
|
||
|
stack = [intervals[0]]
|
||
|
for i in range(1, len(intervals)):
|
||
|
last_element = stack[len(stack) - 1]
|
||
|
if last_element[1][0] >= intervals[i][0][0]:
|
||
|
last_element[1] = max(intervals[i][1], last_element[1], key=lambda x: x[0])
|
||
|
stack.pop(len(stack) - 1)
|
||
|
stack.append(last_element)
|
||
|
else:
|
||
|
stack.append(intervals[i])
|
||
|
return stack
|
||
|
|
||
|
def merge_like_ranges(intervals):
|
||
|
if len(intervals) == 0:
|
||
|
return []
|
||
|
|
||
|
intervals = sorted(intervals, key=lambda x: x[0][0])
|
||
|
|
||
|
stack = [intervals[0]]
|
||
|
for i in range(1, len(intervals)):
|
||
|
last_element = stack[len(stack) - 1]
|
||
|
if last_element[1][0] >= intervals[i][0][0] and last_element[1][1] == intervals[i][1][1]:
|
||
|
last_element[1] = max(intervals[i][1], last_element[1], key=lambda x: x[0])
|
||
|
stack.pop(len(stack) - 1)
|
||
|
stack.append(last_element)
|
||
|
else:
|
||
|
stack.append(intervals[i])
|
||
|
return stack
|
||
|
|
||
|
def list_is_in_order(l):
|
||
|
return all(l[i] <= l[i + 1] for i in range(len(l) - 1))
|
||
|
|
||
|
def program_call(cmd):
|
||
|
subprocess.check_call(cmd, shell=True)
|
||
|
|
||
|
def program_get(cmd):
|
||
|
return subprocess.check_output(cmd, shell=True).decode("ascii")
|
||
|
|
||
|
class XMLWriter:
|
||
|
"""
|
||
|
Simple XML builder for writing with desired formatting characteristics (no tabs, 4 space indent)
|
||
|
"""
|
||
|
|
||
|
def __init__(self):
|
||
|
self.contents = ""
|
||
|
self.tag_stack = []
|
||
|
|
||
|
def __str__(self):
|
||
|
return self.contents
|
||
|
|
||
|
def write_line(self, name, open, close, attributes):
|
||
|
indent = " " * len(self.tag_stack)
|
||
|
if attributes is None:
|
||
|
self.contents += f"{indent}{open}{name}{close}\n"
|
||
|
else:
|
||
|
attributes_str = " ".join(f"{k}=\"{v}\"" for k,v in attributes.items())
|
||
|
self.contents += f"{indent}{open}{name} {attributes_str}{close}\n"
|
||
|
|
||
|
def write_comment(self, comment):
|
||
|
self.write_line(comment, "<!-- ", " -->", None)
|
||
|
|
||
|
def write_start_tag(self, name, attributes=None):
|
||
|
self.write_line(name, "<", ">", attributes)
|
||
|
self.tag_stack.append(name)
|
||
|
|
||
|
def write_end_tag(self):
|
||
|
self.write_line(self.tag_stack.pop(), "</", ">", None)
|
||
|
|
||
|
def write_element(self, name, attributes=None):
|
||
|
self.write_line(name, "<", "/>", attributes)
|
||
|
|
||
|
def write_raw(self, contents):
|
||
|
self.write_line(contents, "", "", None)
|