Mercurial > touhou
comparison pytouhou/formats/exe.py @ 590:e15672733c93
Switch to Python 3.x instead of 2.7.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 30 Sep 2014 17:14:24 +0200 |
parents | b11953cf1d3b |
children | d1f0bb0b7a17 |
comparison
equal
deleted
inserted
replaced
589:0768122da817 | 590:e15672733c93 |
---|---|
72 only be useful for a specific build of the game. | 72 only be useful for a specific build of the game. |
73 """ | 73 """ |
74 | 74 |
75 format = Struct('<4f2I') | 75 format = Struct('<4f2I') |
76 data_section = [section for section in pe_file.sections | 76 data_section = [section for section in pe_file.sections |
77 if section.Name.startswith('.data')][0] | 77 if section.Name.startswith(b'.data')][0] |
78 text_section = [section for section in pe_file.sections | 78 text_section = [section for section in pe_file.sections |
79 if section.Name.startswith('.text')][0] | 79 if section.Name.startswith(b'.text')][0] |
80 data_va = pe_file.image_base + data_section.VirtualAddress | 80 data_va = pe_file.image_base + data_section.VirtualAddress |
81 data_size = data_section.SizeOfRawData | 81 data_size = data_section.SizeOfRawData |
82 text_va = pe_file.image_base + text_section.VirtualAddress | 82 text_va = pe_file.image_base + text_section.VirtualAddress |
83 text_size = text_section.SizeOfRawData | 83 text_size = text_section.SizeOfRawData |
84 | 84 |
85 # Search the whole data segment for 4 successive character definitions | 85 # Search the whole data segment for 4 successive character definitions |
86 for addr in xrange(data_va, data_va + data_size, 4): | 86 for addr in range(data_va, data_va + data_size, 4): |
87 for character_id in xrange(4): | 87 for character_id in range(4): |
88 pe_file.seek_to_va(addr + character_id * 24) | 88 pe_file.seek_to_va(addr + character_id * 24) |
89 (speed1, speed2, speed3, speed4, | 89 (speed1, speed2, speed3, speed4, |
90 ptr1, ptr2) = format.unpack(pe_file.file.read(format.size)) | 90 ptr1, ptr2) = format.unpack(pe_file.file.read(format.size)) |
91 | 91 |
92 # Check whether the character's speed make sense, | 92 # Check whether the character's speed make sense, |
99 | 99 |
100 # So far, this character definition seems to be valid. | 100 # So far, this character definition seems to be valid. |
101 # Now, make sure the shoot function wrappers pass valid addresses | 101 # Now, make sure the shoot function wrappers pass valid addresses |
102 | 102 |
103 # Search for the “push” instruction | 103 # Search for the “push” instruction |
104 for i in xrange(20): | 104 for i in range(20): |
105 # Find the “push” instruction | 105 # Find the “push” instruction |
106 pe_file.seek_to_va(ptr1 + i) | 106 pe_file.seek_to_va(ptr1 + i) |
107 instr1, shtptr1 = unpack('<BI', pe_file.file.read(5)) | 107 instr1, shtptr1 = unpack('<BI', pe_file.file.read(5)) |
108 pe_file.seek_to_va(ptr2 + i) | 108 pe_file.seek_to_va(ptr2 + i) |
109 instr2, shtptr2 = unpack('<BI', pe_file.file.read(5)) | 109 instr2, shtptr2 = unpack('<BI', pe_file.file.read(5)) |
135 | 135 |
136 @classmethod | 136 @classmethod |
137 def read(cls, file): | 137 def read(cls, file): |
138 pe_file = PEFile(file) | 138 pe_file = PEFile(file) |
139 data_section = [section for section in pe_file.sections | 139 data_section = [section for section in pe_file.sections |
140 if section.Name.startswith('.data')][0] | 140 if section.Name.startswith(b'.data')][0] |
141 data_va = pe_file.image_base + data_section.VirtualAddress | 141 data_va = pe_file.image_base + data_section.VirtualAddress |
142 data_size = data_section.SizeOfRawData | 142 data_size = data_section.SizeOfRawData |
143 | 143 |
144 try: | 144 try: |
145 character_records_va = next(cls.find_character_defs(pe_file)) | 145 character_records_va = next(cls.find_character_defs(pe_file)) |
146 except StopIteration: | 146 except StopIteration: |
147 raise InvalidExeException | 147 raise InvalidExeException |
148 | 148 |
149 characters = [] | 149 characters = [] |
150 shots_offsets = {} | 150 shots_offsets = {} |
151 for character in xrange(4): | 151 for character in range(4): |
152 sht = cls() | 152 sht = cls() |
153 | 153 |
154 pe_file.seek_to_va(character_records_va + 6*4*character) | 154 pe_file.seek_to_va(character_records_va + 6*4*character) |
155 | 155 |
156 data = unpack('<4f2I', file.read(6*4)) | 156 data = unpack('<4f2I', file.read(6*4)) |
167 focused_sht = copy(sht) | 167 focused_sht = copy(sht) |
168 characters.append((sht, focused_sht)) | 168 characters.append((sht, focused_sht)) |
169 | 169 |
170 for sht, func_offset in ((sht, shots_func_offset), (focused_sht, shots_func_offset_focused)): | 170 for sht, func_offset in ((sht, shots_func_offset), (focused_sht, shots_func_offset_focused)): |
171 # Search for the “push” instruction | 171 # Search for the “push” instruction |
172 for i in xrange(20): | 172 for i in range(20): |
173 # Find the “push” instruction | 173 # Find the “push” instruction |
174 pe_file.seek_to_va(func_offset + i) | 174 pe_file.seek_to_va(func_offset + i) |
175 instr, offset = unpack('<BI', file.read(5)) | 175 instr, offset = unpack('<BI', file.read(5)) |
176 if instr == 0x68 and 0 <= offset - data_va < data_size - 12: | 176 if instr == 0x68 and 0 <= offset - data_va < data_size - 12: |
177 pe_file.seek_to_va(offset) | 177 pe_file.seek_to_va(offset) |
182 break | 182 break |
183 if offset not in shots_offsets: | 183 if offset not in shots_offsets: |
184 shots_offsets[offset] = [] | 184 shots_offsets[offset] = [] |
185 shots_offsets[offset].append(sht) | 185 shots_offsets[offset].append(sht) |
186 | 186 |
187 for shots_offset, shts in shots_offsets.iteritems(): | 187 for shots_offset, shts in shots_offsets.items(): |
188 pe_file.seek_to_va(shots_offset) | 188 pe_file.seek_to_va(shots_offset) |
189 | 189 |
190 level_count = 9 | 190 level_count = 9 |
191 levels = [] | 191 levels = [] |
192 for i in xrange(level_count): | 192 for i in range(level_count): |
193 shots_count, power, offset = unpack('<III', file.read(3*4)) | 193 shots_count, power, offset = unpack('<III', file.read(3*4)) |
194 levels.append((shots_count, power, offset)) | 194 levels.append((shots_count, power, offset)) |
195 | 195 |
196 shots = {} | 196 shots = {} |
197 | 197 |
198 for shots_count, power, offset in levels: | 198 for shots_count, power, offset in levels: |
199 shots[power] = [] | 199 shots[power] = [] |
200 pe_file.seek_to_va(offset) | 200 pe_file.seek_to_va(offset) |
201 | 201 |
202 for i in xrange(shots_count): | 202 for i in range(shots_count): |
203 shot = Shot() | 203 shot = Shot() |
204 | 204 |
205 data = unpack('<HH6fHBBhh', file.read(36)) | 205 data = unpack('<HH6fHBBhh', file.read(36)) |
206 (shot.interval, shot.delay, x, y, hitbox_x, hitbox_y, | 206 (shot.interval, shot.delay, x, y, hitbox_x, hitbox_y, |
207 shot.angle, shot.speed, shot.damage, shot.orb, shot.type, | 207 shot.angle, shot.speed, shot.damage, shot.orb, shot.type, |