-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdtm2text.py
139 lines (111 loc) · 4.48 KB
/
dtm2text.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import sys
import argparse
import os.path
import struct
from io import BytesIO
def byte_inputs_from_file(movie):
"Generate input data from DTM movie."
input_bytes = 8
while True:
input_data = movie.read(input_bytes)
if not input_data:
break
yield input_data
def text_input_from_bytes(input_data):
"Convert DTM input data to text."
flags, l, r, a_x, a_y, c_x, c_y = struct.unpack("H6B", input_data)
start_flag = flags & 1
a_flag = flags >> 1 & 1
b_flag = flags >> 2 & 1
x_flag = flags >> 3 & 1
y_flag = flags >> 4 & 1
z_flag = flags >> 5 & 1
d_up = flags >> 6 & 1
d_down = flags >> 7 & 1
d_left = flags >> 8 & 1
d_right = flags >> 9 & 1
l_flag = flags >> 10 & 1
r_flag = flags >> 11 & 1
button_data = (start_flag, a_flag, b_flag, x_flag, y_flag,
z_flag, d_up, d_down, d_left, d_right, l_flag,
r_flag, l, r, a_x, a_y, c_x, c_y)
return ":".join(str(b) for b in button_data)
def byte_input_from_text(input_data):
"Convert text input data to DTM."
if input_data == '\n':
result = b''
elif input_data[0] == '#':
result = b''
else:
start_flag, a_flag, b_flag, x_flag, y_flag, z_flag, d_up, d_down, d_left, d_right, l_flag, r_flag, l, r, a_x, a_y, c_x, c_y = (int(b) for b in input_data.split(":"))
flags = r_flag
flags = flags << 1 | l_flag
flags = flags << 1 | d_right
flags = flags << 1 | d_left
flags = flags << 1 | d_down
flags = flags << 1 | d_up
flags = flags << 1 | z_flag
flags = flags << 1 | y_flag
flags = flags << 1 | x_flag
flags = flags << 1 | b_flag
flags = flags << 1 | a_flag
flags = flags << 1 | start_flag
result = struct.pack("H6B", flags, l, r, a_x, a_y, c_x, c_y)
return result
def text2dtm(argv=None):
if argv is None:
argv = sys.argv
description = ('Convert header + plain text input data to DTM.')
parser = argparse.ArgumentParser(description=description,
fromfile_prefix_chars='@')
parser.add_argument('output', help='output file name')
parser.add_argument('header', help='256 byte header file')
parser.add_argument('infile', nargs='?', default='-',
help='file of inputs, one per line;'
' if none provided, defaults to stdin')
args = parser.parse_args(argv[1:])
movie_path = args.output
header_path = args.header
input_path = args.infile
i = 0
movie_data = BytesIO()
with open(header_path, mode='rb') as bin_header_file:
movie_data.write(bin_header_file.read())
with open(input_path, mode='r') if input_path is not '-' else sys.stdin as text_input_file:
for text_input in text_input_file:
byte_input = byte_input_from_text(text_input)
if byte_input:
i += 1
movie_data.write(byte_input)
movie_view = movie_data.getbuffer()
movie_view[13:21] = struct.pack("Q", i // 2) # trick the frame data
movie_view[21:29] = struct.pack("Q", i) # set the input count
movie_view[237:245] = struct.pack("Q", i * 2125000) # trick the tick count
with open(movie_path, mode='wb') as bin_movie_file:
bin_movie_file.write(movie_data.getvalue())
return 0
def dtm2text(argv=None):
if argv is None:
argv = sys.argv
description = ('Convert DTM to header file + plain text input data.')
parser = argparse.ArgumentParser(description=description)
parser.add_argument('movie', help='the DTM to dump')
args = parser.parse_args(argv[1:])
movie_path = args.movie
movie_basename = os.path.basename(movie_path)
header_bytes = 256
header_path = "{}_header".format(movie_basename)
input_path = "{}_inputs.txt".format(movie_basename)
with open(movie_path, mode='rb') as bin_movie_file:
# This has the side effect of advancing the movie file.
# That's a good thing in our case.
header_bytes = bin_movie_file.read(header_bytes)
with open(header_path, mode='wb') as bin_header_file:
bin_header_file.write(header_bytes)
with open(input_path, mode='w') as text_input_file:
for byte_input in byte_inputs_from_file(bin_movie_file):
text_input = text_input_from_bytes(byte_input)
text_input_file.write(text_input + "\n")
return 0
if __name__ == '__main__':
sys.exit(dtm2text())