Skip to content

Commit

Permalink
Add reload&diff function
Browse files Browse the repository at this point in the history
  • Loading branch information
maikelwever committed Mar 7, 2021
1 parent d6f16aa commit d6c36be
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
crossfiledialog
bimpy==0.1.1
mymcplus==3.0.4
diff-match-patch==20200713
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

setup(
name='slimseditor',
version='0.0.5',
version='0.0.6',
description='A savegame editor for the Ratchet and Clank games',
author='Maikel Wever',
author_email='[email protected]',
Expand Down
36 changes: 35 additions & 1 deletion slimseditor/frames.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from collections import defaultdict
from datetime import datetime
from io import BytesIO

import bimpy
import crossfiledialog

from diff_match_patch import diff_match_patch
from mymcplus import ps2mc

from slimseditor.backends import AbstractBackend, PS2WrappedBinBackend

from slimseditor.hexdump import hexdump

counter = 0

Expand All @@ -18,6 +20,11 @@ def get_next_count():
return value


def format_patchline(t, text):
text = text.strip('\n').replace('\n', '\n ')
return f"{'+' if t == 1 else '-'} {text}"


class FrameBase:
def __init__(self):
self._size = None
Expand All @@ -42,6 +49,7 @@ def __init__(self, backend_class, *backend_args, **backend_kwargs):
self.load_backend()

self.name = '{0}##{1}'.format(self.backend.get_friendly_name(), get_next_count())
self.diff_string = ""

def load_backend(self):
self.backend = self.backend_class(*self.backend_args, **self.backend_kwargs) # type: AbstractBackend
Expand All @@ -62,8 +70,12 @@ def render(self):
bimpy.menu_item('Save', 'Cmd+S', self.click_states['save'])
bimpy.menu_item('Reload', 'Cmd+R', self.click_states['reload'])
bimpy.menu_item('Export', 'Cmd+E', self.click_states['export'])
bimpy.menu_item('Reload & Diff', 'Cmd+D', self.click_states['reload_and_diff'])
bimpy.end_menu_bar()

if self.diff_string:
bimpy.columns(2, "hex split")

bimpy.text('Game: ')
bimpy.same_line()
bimpy.text(self.backend.game.value)
Expand All @@ -73,8 +85,26 @@ def render(self):
for item in section_items:
item.render_widget()

if self.diff_string:
bimpy.next_column()
bimpy.text(self.diff_string)

bimpy.end()

def reload_and_diff(self):
pre_reload_hex = hexdump(self.backend.data, print_ascii=False)
self.load_backend()
post_reload_hex = hexdump(self.backend.data, print_ascii=False)

patcher = diff_match_patch()
text1, text2, line_array = patcher.diff_linesToChars(pre_reload_hex, post_reload_hex)
diffs = patcher.diff_main(text1, text2)
patcher.diff_cleanupSemantic(diffs)
patcher.diff_charsToLines(diffs, line_array)
patch = '\n'.join(format_patchline(t, text) for t, text in diffs if t != 0)

self.diff_string = f'{datetime.now()}\n{patch}\n\n{self.diff_string}'

def process_events(self):
if self.click_states['save'].value:
self.backend.write_all_items(self.items)
Expand All @@ -85,6 +115,10 @@ def process_events(self):
self.load_backend()
self.click_states['reload'].value = False

if self.click_states['reload_and_diff'].value:
self.reload_and_diff()
self.click_states['reload_and_diff'].value = False

if self.click_states['export'].value:
filename = crossfiledialog.save_file()
if filename:
Expand Down
39 changes: 39 additions & 0 deletions slimseditor/hexdump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3

"""
Hexdump by 7hrrAm from https://gist.github.com/7h3rAm/5603718
Based in part on sbz version from https://gist.github.com/sbz/1080258
Modified by maikelwever to make ascii printing optional.
"""

def hexdump(src, length=16, sep='.', print_ascii=True):
"""
>>> print(hexdump('\x01\x02\x03\x04AAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBB'))
00000000: 01 02 03 04 41 41 41 41 41 41 41 41 41 41 41 41 |....AAAAAAAAAAAA|
00000010: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 |AAAAAAAAAAAAAABB|
00000020: 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 |BBBBBBBBBBBBBBBB|
00000030: 42 42 42 42 42 42 42 42 |BBBBBBBB|
>>>
>>> print(hexdump(b'\x01\x02\x03\x04AAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBB'))
00000000: 01 02 03 04 41 41 41 41 41 41 41 41 41 41 41 41 |....AAAAAAAAAAAA|
00000010: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 |AAAAAAAAAAAAAABB|
00000020: 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 |BBBBBBBBBBBBBBBB|
00000030: 42 42 42 42 42 42 42 42 |BBBBBBBB|
"""
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or sep for x in range(256)])
lines = []
for c in range(0, len(src), length):
chars = src[c:c+length]
hexstr = ' '.join(["%02x" % ord(x) for x in chars]) if type(chars) is str else ' '.join(['{:02x}'.format(x) for x in chars])
if len(hexstr) > 24:
hexstr = "%s %s" % (hexstr[:24], hexstr[24:])
if print_ascii:
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or sep) for x in chars]) if type(chars) is str else ''.join(['{}'.format((x <= 127 and FILTER[x]) or sep) for x in chars])
lines.append("%08x: %-*s |%s|" % (c, length*3, hexstr, printable))
else:
lines.append("%08x: %-*s" % (c, length * 3, hexstr))
return '\n'.join(lines)

if __name__ == "__main__":
print(hexdump('\x01\x02\x03\x04AAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBB'))
print(hexdump(b'\x01\x02\x03\x04AAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBB'))

0 comments on commit d6c36be

Please sign in to comment.