~thestr4ng3r/mymcplus

ref: cff55ba378c47ff60022bf5bed1911a98d4b765b mymcplus/mymcplus/save/format_ems.py -rw-r--r-- 3.4 KiB
cff55ba3 — Kistelini Fix Usages of removed from/tostring for Python 3.9 (#10) 9 months ago
                                                                                
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
#
# This file is part of mymc+, based on mymc by Ross Ridge.
#
# mymc+ is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# mymc+ is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with mymc+.  If not, see <http://www.gnu.org/licenses/>.
#

from . import ps2save
from .. import ps2mc_dir
from .utils import *
from ..round import round_up


FORMAT_ID = "psu"


def poll(hdr):
    #
    # EMS (.psu) save files don't have a magic number.  Check to
    # see if it looks enough like one.
    #

    if len(hdr) < ps2mc_dir.PS2MC_DIRENT_LENGTH * 3:
        return None

    dirent = ps2mc_dir.unpack_dirent(hdr[:ps2mc_dir.PS2MC_DIRENT_LENGTH])
    dotent = ps2mc_dir.unpack_dirent(hdr[ps2mc_dir.PS2MC_DIRENT_LENGTH : ps2mc_dir.PS2MC_DIRENT_LENGTH * 2])
    dotdotent = ps2mc_dir.unpack_dirent(hdr[ps2mc_dir.PS2MC_DIRENT_LENGTH * 2:])

    return ps2mc_dir.mode_is_dir(dirent[0]) and ps2mc_dir.mode_is_dir(dotent[0]) \
            and ps2mc_dir.mode_is_dir(dotdotent[0]) and dirent[2] >= 2 \
            and dotent[8] == b"." and dotdotent[8] == b".."


def load(save, f):
    """Load EMS (.psu) save files."""

    cluster_size = 1024

    dirent = ps2mc_dir.unpack_dirent(read_fixed(f, ps2mc_dir.PS2MC_DIRENT_LENGTH))
    dotent = ps2mc_dir.unpack_dirent(read_fixed(f, ps2mc_dir.PS2MC_DIRENT_LENGTH))
    dotdotent = ps2save.unpack_dirent(read_fixed(f, ps2mc_dir.PS2MC_DIRENT_LENGTH))
    if (not ps2mc_dir.mode_is_dir(dirent[0])
            or not ps2save.mode_is_dir(dotent[0])
            or not ps2save.mode_is_dir(dotdotent[0])
            or dirent[2] < 2):
        raise ps2save.Corrupt("Not a EMS (.psu) save file.", f)

    dirent[2] -= 2
    save.set_directory(dirent)

    for i in range(dirent[2]):
        ent = ps2mc_dir.unpack_dirent(read_fixed(f, ps2mc_dir.PS2MC_DIRENT_LENGTH))
        if not ps2mc_dir.mode_is_file(ent[0]):
            raise ps2save.Subdir(f)
        flen = ent[2]
        save.set_file(i, ent, read_fixed(f, flen))
        read_fixed(f, round_up(flen, cluster_size) - flen)


def save(save, f):
    cluster_size = 1024

    dirent = save.dirent[:]
    dirent[2] += 2
    f.write(ps2mc_dir.pack_dirent(dirent))
    f.write(ps2mc_dir.pack_dirent((ps2mc_dir.DF_RWX | ps2mc_dir.DF_DIR | ps2mc_dir.DF_0400 | ps2mc_dir.DF_EXISTS,
                                   0, 0, dirent[3],
                                   0, 0, dirent[3], 0, b".")))
    f.write(ps2mc_dir.pack_dirent((ps2mc_dir.DF_RWX | ps2mc_dir.DF_DIR | ps2mc_dir.DF_0400 | ps2mc_dir.DF_EXISTS,
                                   0, 0, dirent[3],
                                   0, 0, dirent[3], 0, b"..")))

    for i in range(dirent[2] - 2):
        (ent, data) = save.get_file(i)
        f.write(ps2mc_dir.pack_dirent(ent))
        if not ps2mc_dir.mode_is_file(ent[0]):
            # print ent
            # print hex(ent[0])
            raise ps2save.Error("Directory has a subdirectory.")
        f.write(data)
        f.write(b"\0" * (round_up(len(data), cluster_size) - len(data)))
    f.flush()