mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
KDL3: Version 2.0.0 (#3323)
* initial work on procedure patch * more flexibility load default procedure for version 5 patches add args for procedure add default extension for tokens and bsdiff allow specifying additional required extensions for generation * pushing current changes to go fix tloz bug * move tokens into a separate inheritable class * forgot the commit to remove token from ProcedurePatch * further cleaning from bad commit * start on docstrings * further work on docstrings and typing * improve docstrings * fix incorrect docstring * cleanup * clean defaults and docstring * define interface that has only the bare minimum required for `Patch.create_rom_file` * change to dictionary.get * remove unnecessary if statement * update to explicitly check for procedure, restore compatible version and manual override * Update Files.py * remove struct uses * Update Rom.py * convert KDL3 to APPP * change class variables to instance variables * Update worlds/Files.py Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> * Update worlds/Files.py Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> * move required_extensions to tuple * fix missing tuple ellipsis * fix classvar mixup * rename tokens to _tokens. use hasattr * type hint cleanup * Update Files.py * initial base for local items, need to finish * coo not clean * handle local items for real, appp cleanup * actually make bosses send their locations * fix cloudy park 4 rule, zero deathlink message * remove redundant door_shuffle bool when generic ER gets in, this whole function gets rewritten. So just clean it a little now. * properly fix deathlink messages, fix fill error * update docs * add prefill items * fix kine fill error * Update Rom.py * Update Files.py * mypy and softlock fix * Update Gifting.py * mypy phase 1 * fix rare async client bug * Update __init__.py * typing cleanup * fix stone softlock because of the way Kine's Stone works, you can't clear the stone blocks before clearing the burning blocks, so we have to bring Burning from outside * Update Rom.py * Add option groups * Rename to lowercase * finish rename * whoops broke the world * fix animal duplication bug * overhaul filler generation * add Miku flavor * Update gifting.py * fix issues related to max_hs increase * Update test_locations.py * fix boss shuffle not working if level shuffle is disabled * fix bleeding default levels * Update options.py * thought this would print seed * yay bad merges * forgot options too * yeah lets just break generation while at it * this is probably a problem * cap required heart stars * Revert "cap required heart stars" This reverts commit 759efd3e2b14ec2855082de041ac989cb9c5d500. * fix duplication removal placement, deprecated test option * forgot that we need to account for what we place * move location ids * rewrite trap handling * further stage renumber fixes * forgot one more * basic UT support * fix local heart star checks * fix pattern --------- Co-authored-by: beauxq <beauxq@yahoo.com> Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
This commit is contained in:
57
worlds/kdl3/compression.py
Normal file
57
worlds/kdl3/compression.py
Normal file
@@ -0,0 +1,57 @@
|
||||
def hal_decompress(comp: bytes) -> bytes:
|
||||
"""
|
||||
HAL decompression based on exhal by devinacker
|
||||
https://github.com/devinacker/exhal
|
||||
"""
|
||||
inpos = 0
|
||||
|
||||
inval = 0
|
||||
output = bytearray()
|
||||
while inval != 0xFF:
|
||||
remaining = 65536 - inpos
|
||||
if remaining < 1:
|
||||
return bytes()
|
||||
inval = comp[inpos]
|
||||
inpos += 1
|
||||
if inval == 0xFF:
|
||||
break
|
||||
if (inval & 0xE0) == 0xE0:
|
||||
command = (inval >> 2) & 0x07
|
||||
length = (((inval & 0x03) << 8) | comp[inpos]) + 1
|
||||
inpos += 1
|
||||
else:
|
||||
command = inval >> 5
|
||||
length = (inval & 0x1F) + 1
|
||||
if (command == 2 and ((len(output) + 2*length) > 65536)) or (len(output) + length) > 65536:
|
||||
return bytes()
|
||||
if command == 0:
|
||||
output.extend(comp[inpos:inpos+length])
|
||||
inpos += length
|
||||
elif command == 1:
|
||||
output.extend([comp[inpos] for _ in range(length)])
|
||||
inpos += 1
|
||||
elif command == 2:
|
||||
output.extend([comp[x] for _ in range(length) for x in (inpos, inpos+1)])
|
||||
inpos += 2
|
||||
elif command == 3:
|
||||
output.extend([comp[inpos] + i for i in range(length)])
|
||||
inpos += 1
|
||||
elif command == 4 or command == 7:
|
||||
offset = (comp[inpos] << 8) | comp[inpos + 1]
|
||||
if (offset + length) > 65536:
|
||||
return bytes()
|
||||
output.extend(output[offset:offset+length])
|
||||
inpos += 2
|
||||
elif command == 5:
|
||||
offset = (comp[inpos] << 8) | comp[inpos + 1]
|
||||
if (offset + length) > 65536:
|
||||
return bytes()
|
||||
output.extend([int('{:08b}'.format(x)[::-1], 2) for x in output[offset:offset+length]])
|
||||
inpos += 2
|
||||
elif command == 6:
|
||||
offset = (comp[inpos] << 8) | comp[inpos + 1]
|
||||
if offset < length - 1:
|
||||
return bytes()
|
||||
output.extend([output[offset - x] for x in range(length)])
|
||||
inpos += 2
|
||||
return bytes(output)
|
||||
Reference in New Issue
Block a user