def __init__(self, path=None, data=None, yj1=True): # path和data不能同时是None assert path or data self.yj1 = YJ1Decoder() if yj1 else None try: # 优先使用path(优先从文件读取) if path: with open(path, 'rb') as f: self._content = memoryview(f.read()) else: self._content = memoryview(data) # 偏移(索引)表长度,假设文件前4位为6C 02 00 00(little-end的int值为 # 26CH = 620),说明索引表长度为620字节,即620/4 = 155个整数,由于第一个 # 整数被用于存储表长度,因此实际上只有后面154个整数存的是偏移量。另一方面, # 最后一个整数指向文件末尾,也就是文件的长度,因此实际上MKF内部的文件是由 # 前后两个偏移量之间的byte表示的。这样由于一共有154个个偏移量,因此共有 # 153个文件 # # !!!补充:第一个int(前四位)不仅是偏移表长度,也是第一个文件的开头 # ABC.MKF中前面两个4位分别相等只是巧合(第一个文件为0) self.count = unpack_from('<I', self._content, 0)[0] // 4 # - 1 self.indexes = tuple( unpack_from('<I', self._content, i << 2)[0] for i in range(self.count)) self.cache = [None] * self.count # 减去最后一个偏移量,对外而言,count就表示mkf文件中的子文件个数 self.count -= 1 except IOError: raise IOError('error occurs when try to open file ' + path) except TypeError: raise TypeError('data can not be converted to memoryview')
def __init__(self, word_length): self.word_length = word_length with open('word.dat', 'rb') as f: self.data = f.read() global encoding if encoding is None: encoding = chardet.detect(self.data)['encoding'] if encoding.lower() in {'gb2312', 'iso-8859-1'}: encoding = 'gbk' self.init_fonts()
def get_saved_times(self, index, path=None): if path is None: path = str(index) + '.rpg' try: with open(path, 'rb') as fin: head = fin.read(2) if len(head): return unpack('H', head)[0] else: return 0 except FileNotFoundError: return 0
def load(self, index): try: name = open('./Musics/%.3d.mid' % index, 'rb') self.midifile = mido.MidiFile(file=name) return True except (FileNotFoundError, ValueError): try: midi_mkf = MKFDecoder('midi.mkf', yj1=False) data = midi_mkf.read(index, True) except Exception: data = '' if len(data): name = BytesIO(data) self.midifile = mido.MidiFile(file=name) return True else: self.midifile = mido.MidiFile() return False
def __init__(self): self.shake_time = 0 self.shake_level = 0 self.num_palette = 0 self.night_palette = False self.need_fadein = False offset = 0x28 max_index = 11 file_size = 0x300 try: with open('pat.mkf', 'rb') as f: content = bytearray(f.read()) # 新建一个数组保存11个调色板文件(每个调色板256种颜色) self.palettes = [[ pg.Color(*(x << 2 for x in content[pos:pos + 3])) for pos in range(index, index + file_size, 3) ] for index in range(offset, offset + max_index * file_size, file_size)] except IOError: print('error occurs when try to open file pat.mkf')
def load_game(self, index, path=None): if index == 0: self.load_default_game() return try: if path is None: path = '%d.rpg' % index with open(path, 'rb') as f: save = SavedGame.from_file(f) self.battle_speed = save.battle_speed self.cash = save.cash self.viewport = save.viewport self.max_party_member_index = save.party_member_num self.num_scene = save.num_scene self.night_palette = save.palette_offset != 0 self.party_direction = save.party_direction self.num_music = save.num_music self.num_battle_music = save.num_battle_music self.num_battle_field = save.num_battle_field self.screen_wave = save.screen_wave self.wave_progression = 0 self.collect_value = save.collect_value self.layer = save.layer self.chase_range = save.chase_range self.chasespeed_change_cycles = save.chasespeed_change_cycles self.follower_num = save.follower_num self.party = save.party self.trail = save.trail self.exp = save.exp self.player_roles = save.player_roles self.poison_status = PoisonStatusTable(None) self.inventory = save.inventory self.scenes = read_by_struct(Scene, save.scene._buffer) self.event_objects = read_by_struct(Event, save.event_object._buffer) self.objects = read_by_struct(Obj, save.object._buffer) self.entering_scene = False self.compress_inventory() except Exception: self.load_default_game()
def save_game(self, index, saved_times, path=None): if path is None: path = '%d.rpg' % index save = SavedGame(None) save.saved_times = saved_times save.viewport = self.viewport save.party_member_num = self.max_party_member_index save.num_scene = self.num_scene save.palette_offset = 0x180 if self.night_palette else 0 save.party_direction = self.party_direction save.num_music = self.num_music save.num_battle_music = self.num_battle_music save.num_battle_field = self.num_battle_field save.screen_wave = self.screen_wave save.collect_value = self.collect_value save.layer = self.layer save.chase_range = self.chase_range save.chasespeed_change_cycles = self.chasespeed_change_cycles save.follower_num = self.follower_num save.cash = self.cash save.battle_speed = 2 save.party = self.party save.trail = self.trail save.exp = self.exp save.poison_status = self.poison_status save.inventory = self.inventory save.player_roles = self.player_roles for i, _ in enumerate(self.event_objects): save.event_object[i] = self.event_objects[i] for i, _ in enumerate(self.objects): save.object[i] = self.objects[i] for i, _ in enumerate(self.scenes): save.scene[i] = self.scenes[i] with open(path, 'wb') as f: f.write( save._buffer.tobytes()[:len(self.sss.read(0)) + save.struct_size - Event.struct_size * MAX_EVENT_OBJECTS])
def __init__(self): with open('desc.dat', 'rb') as f: self.descs = {} content = f.read().decode(encoding, errors="replace") for index, name, desc in self.DESC_RE.findall(content): self.descs[int(index, 16)] = desc.strip()
def __init__(self): self.word_length = 10 if config['msg_file']: with open(config['msg_file'], 'rb') as f: content = f.read() cfg_content, msg_content = content.split( b'\n[BEGIN MESSAGE]', 1) msg_content = b'[BEGIN MESSAGE]' + msg_content cfg = ConfigObj(BytesIO(cfg_content), encoding='utf-8') if cfg['BEGIN SETTING']['UseISOFont']: config['use_iso_font'] = True self.words = { int(i): word for i, word in cfg['BEGIN WORDS'].items() } self.msgs = [] self.msg_index = {} for sid, block, eid in re.findall( u'\[BEGIN MESSAGE\] (\d+)([\s\S]+?)\[END MESSAGE\] (\d+)', msg_content.decode('utf-8'), re.UNICODE): item = int(sid) self.msg_index[item] = [] for line in block.strip().splitlines(): if line != '[CLEAR MESSAGE]': self.msg_index[item].append(len(self.msgs)) self.msgs.append(line) else: self.msg_index[item].append(0) offset = 1 for slot in self.screen_layout.__slots__: attr = getattr(self.screen_layout, slot) if isinstance(attr, list): for i in range(len(attr)): attr[i] = tuple( int(x) for x in cfg['BEGIN LAYOUT'][str(offset)]) offset += 1 elif isinstance(attr, tuple): item = tuple( int(x) for x in cfg['BEGIN LAYOUT'][str(offset)]) setattr(self.screen_layout, slot, item) offset += 1 if offset == 75: offset = 81 self.use_custom_screen_layout = True else: self.words = Word(self.word_length) self.msgs = Msg() self.use_custom_screen_layout = False self.delay_time = 3 self.updated_in_battle = False self.current_dialog_line_num = 0 self.dialog_icons = SubPlace(Data().read(12)) self.current_font_color = FONT_COLOR_DEFAULT self.icon = 0 self.pos_icon = 0 self.pos_dialog_title = 12, 8 self.pos_dialog_text = 44, 26 self.dialog_position = DialogPos.Upper self.dialog_shadow = 0 self.user_skip = False try: self.descs = Desc() except Exception: self.descs = None self.no_desc = False
def __init__(self): self.indexes = SSS().read(3) msg_file = 'm.msg' with open(msg_file, 'rb') as f: self.msg = f.read()
def init_fonts(self): if config['use_embedded_font']: global char_data with open('wor16.asc', 'rb') as f: content = f.read() char_data = content.decode(encoding, 'replace')
AAAA/Y2NjYz8bM2NjAAAAAAA+YwMDDjhg\nYGM+AAAAAAB+GBgYGBgYGBgYAAAAAABjY2NjY2 NjY2M+AAAAAABjY2NjYzY2HBwIAAAAAABjY2tr\na2t/NjY2AAAAAABjYzY2HBw2NmNjAAAAA ADDw2ZmPDwYGBgYAAAAAAB/MDAYGAwMBgZ/AAAAAAA8\nDAwMDAwMDAw8AAAAAAADAgYEDAgY EDAgYAAAAAA8MDAwMDAwMDA8AAAAAAgcNmMAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAP8AAAA MDBgAAAAAAAAAAAAAAAAAAAA+YH5jY3NuAAAAAAADAwM7Z2NjY2c7\nAAAAAAAAAAA+YwMDA2 M+AAAAAABgYGBuc2NjY3NuAAAAAAAAAAA+Y2N/A2M+AAAAAAA8ZgYfBgYG\nBgYGAAAAAAAAA ABuc2NjY3NuYGM+AAADAwM7Z2NjY2NjAAAAAAAMDAAMDAwMDAw4AAAAAAAwMAAw\nMDAwMDAw MDMeAAADAwNjMxsPHzNjAAAAAAAMDAwMDAwMDAw4AAAAAAAAAAA1a2tra2trAAAAAAAA\nAAA 7Z2NjY2NjAAAAAAAAAAA+Y2NjY2M+AAAAAAAAAAA7Z2NjY2c7AwMDAAAAAABuc2NjY3NuYOB g\nAAAAAAA7ZwMDAwMDAAAAAAAAAAA+Yw44YGM+AAAAAAAADAw+DAwMDAw4AAAAAAAAAABjY2 NjY3Nu\nAAAAAAAAAABjYzY2HBwIAAAAAAAAAABja2trPjY2AAAAAAAAAABjNhwcHDZjAAAAA AAAAABjYzY2\nHBwMDAYDAAAAAAB/YDAYDAZ/AAAAAABwGBgYGA4YGBgYcAAAABgYGBgYGBgY GBgYGAAAAAAOGBgY\nGHAYGBgYDgAAAAAAAAAAbjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA''')) if config['use_embedded_font']: with open('wor16.fon', 'rb') as f: pos = 0x682 f.seek(pos) font_data = bytearray(f.read()) if not (config['use_embedded_font'] and config['use_iso_font']): freetype.init() unicode_font = freetype.Font(config['font_file'], 16) def get_char_width(o): width = wcwidth.wcwidth(o) return width << 3 class Desc(Object):