WTS/game/scripts/utility/punk.rpy

138 lines
4.4 KiB
Plaintext

#####################################
## Created by briandeheus ##
## https://github.com/briandeheus ##
## Implementation and changes ##
## LoafyLemon ##
#####################################
init python:
import binascii
import struct
class ImagePayload(object):
_END_CHUNK_TYPE = 'IEND'
_PUNK_CHUNK_TYPE = 'wtSi'
_MAX_BYTES = 2147483647
_chunks = dict()
def __init__(self):
self._mode = None
self._file = None
self._output = None
self._bytes_to_hide = None
self._bytes_read = 0
def decode(self, input_file):
self.__init__()
self._mode = 'decode'
self._file = open("{}/outfits/{}".format(config.gamedir, input_file), 'rb+')
#self._output = open(config.basedir+'/game/'+output_file+'.txt', 'wb+')
# First move cursor past the signature
self._read_bytes(8)
# Start reading chunks
self._read_next_chunk()
return self._output
def encode(self, input_file, bytes_to_hide):
self.__init__()
self._mode = 'encode'
self._file = open("{}/outfits/{}.png".format(config.gamedir, input_file), 'rb+')
self._bytes_to_hide = bytes_to_hide.encode('utf-8')
# First move cursor past the signature
self._read_bytes(8)
# Start reading chunks
self._read_next_chunk()
def _read_bytes_as_hex(self, position):
return self._read_bytes(position).encode('hex')
def _read_bytes_as_ascii(self, position):
return self._read_bytes(position).encode('ascii')
def _read_bytes_as_int(self, position):
return int(self._read_bytes_as_hex(position), 16)
def _read_bytes(self, byte_count):
self._bytes_read += byte_count
return self._file.read(byte_count)
def _rewind_bytes(self, byte_count):
self._bytes_read -= byte_count
self._file.seek(self._bytes_read)
def _inject_punk_chunk(self):
# Move back 8 bytes.
self._rewind_bytes(8)
chunk_size = len(self._bytes_to_hide)
print 'Hiding', (chunk_size / 1024), 'kB (', chunk_size, 'bytes)'
# Create a temporary byte array for the CRC check.
tmp_bytes = bytearray()
# First write the chunk type
tmp_bytes.extend(bytearray(self._PUNK_CHUNK_TYPE))
# Now write the bytes of whatever we're trying to hide
tmp_bytes.extend(self._bytes_to_hide)
#print 'Injecting punk chunk'
# Write the chunk size
self._file.write(bytearray(struct.pack('!i', chunk_size)))
# And the type
self._file.write(bytearray(self._PUNK_CHUNK_TYPE))
self._file.write(self._bytes_to_hide)
crc = binascii.crc32(tmp_bytes)
self._file.write(bytearray(struct.pack('!i', crc)))
# Write the end chunk. Start with the size.
self._file.write(bytearray(struct.pack('!i', 0)))
# Then the chunk type.
self._file.write(bytearray(self._END_CHUNK_TYPE))
crc = binascii.crc32(bytearray(self._END_CHUNK_TYPE))
self._file.write(bytearray(struct.pack('!i', crc)))
#print 'Punk chunk injected'
def _read_next_chunk(self):
chunk_size = self._read_bytes_as_int(4)
print 'Chunk size:', chunk_size
chunk_type = self._read_bytes_as_ascii(4)
print 'Chunk type:', chunk_type
if self._mode == 'encode' and chunk_type == self._END_CHUNK_TYPE:
self._inject_punk_chunk()
#print 'Reached EOF'
self._file.close()
return
content = self._read_bytes(chunk_size)
crc = self._read_bytes_as_hex(4)
print 'CRC:', crc
if self._mode == 'decode' and chunk_type == self._PUNK_CHUNK_TYPE:
print "Found a chunk data", len(content), "bytes. Importing.."
#self._output.write(bytearray(content))
#self._output.close()
self._output = content.decode('utf-8')
self._file.close()
print "Done."
return True
self._read_next_chunk()
image_payload = ImagePayload()