예제 #1
0
    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')
예제 #2
0
 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()
예제 #3
0
 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
예제 #4
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
예제 #5
0
    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')
예제 #6
0
 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()
예제 #7
0
 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])
예제 #8
0
 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()
예제 #9
0
 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
예제 #10
0
 def __init__(self):
     self.indexes = SSS().read(3)
     msg_file = 'm.msg'
     with open(msg_file, 'rb') as f:
         self.msg = f.read()
예제 #11
0
 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')
예제 #12
0
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):