mirror of
https://github.com/ps2dev/mymc.git
synced 2024-11-30 21:27:16 +01:00
Merge pull request #2 from uyjulian/2.6src
Update sources to 2.6 from author's website
This commit is contained in:
commit
8cdf72b321
10
README.txt
Normal file → Executable file
10
README.txt
Normal file → Executable file
@ -3,7 +3,7 @@ README.txt
|
|||||||
By Ross Ridge
|
By Ross Ridge
|
||||||
Pubic Domain
|
Pubic Domain
|
||||||
|
|
||||||
@(#) mymc README.txt 1.5 08/02/06 13:26:26
|
@(#) mymc README.txt 1.6 12/10/04 19:18:08
|
||||||
|
|
||||||
|
|
||||||
This file describes mymc, a utility for manipulating PlayStation 2
|
This file describes mymc, a utility for manipulating PlayStation 2
|
||||||
@ -109,15 +109,15 @@ saves to someone else to use or just keep them on your hard drive as a
|
|||||||
backup. The following command demonstrates how to export a save in
|
backup. The following command demonstrates how to export a save in
|
||||||
the EMS format using mymc:
|
the EMS format using mymc:
|
||||||
|
|
||||||
c:\mymc\mymc c:\pcsx2\memcards\Mcd001.ps2 export BASLUS-20448-000D
|
c:\mymc\mymc c:\pcsx2\memcards\Mcd001.ps2 export BASLUS-20448-0000D
|
||||||
|
|
||||||
This will create a file called "BASLUS-20448-000D.psu" in the current
|
This will create a file called "BASLUS-20448-0000D.psu" in the current
|
||||||
directory. To create a file in the MAX format instead, use the export
|
directory. To create a file in the MAX format instead, use the export
|
||||||
command's -m option:
|
command's -m option:
|
||||||
|
|
||||||
c:\mymc\mymc c:\pcsx2\memcards\Mcd001.ps2 export -m BASLUS-20448-000D
|
c:\mymc\mymc c:\pcsx2\memcards\Mcd001.ps2 export -m BASLUS-20448-0000D
|
||||||
|
|
||||||
This creates a file named "BASLUS-20448-000D.max". Note the "-m"
|
This creates a file named "BASLUS-20448-0000D.max". Note the "-m"
|
||||||
option that appears after the "export" command.
|
option that appears after the "export" command.
|
||||||
|
|
||||||
Importing save files is similar. The save file type is auto-detected,
|
Importing save files is similar. The save file type is auto-detected,
|
||||||
|
15
gui.py
Normal file → Executable file
15
gui.py
Normal file → Executable file
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
"""Graphical user-interface for mymc."""
|
"""Graphical user-interface for mymc."""
|
||||||
|
|
||||||
_SCCS_ID = "@(#) mymc gui.py 1.3 08/02/06 13:15:41\n"
|
_SCCS_ID = "@(#) mymc gui.py 1.4 12/10/04 18:51:51\n"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -482,12 +482,17 @@ class gui_frame(wx.Frame):
|
|||||||
def mc_error(self, value, filename = None):
|
def mc_error(self, value, filename = None):
|
||||||
"""Display a message box for EnvironmentError exeception."""
|
"""Display a message box for EnvironmentError exeception."""
|
||||||
|
|
||||||
|
if filename == None:
|
||||||
|
filename = getattr(value, "filename")
|
||||||
if filename == None:
|
if filename == None:
|
||||||
filename = self.mcname
|
filename = self.mcname
|
||||||
if filename == None:
|
if filename == None:
|
||||||
filename = "???"
|
filename = "???"
|
||||||
filename = getattr(value, "filename", filename)
|
|
||||||
strerror = getattr(value, "strerror", "unknown error")
|
strerror = getattr(value, "strerror", None)
|
||||||
|
if strerror == None:
|
||||||
|
strerror = "unknown error"
|
||||||
|
|
||||||
return self.error_box(filename + ": " + strerror)
|
return self.error_box(filename + ": " + strerror)
|
||||||
|
|
||||||
def __init__(self, parent, title, mcname = None):
|
def __init__(self, parent, title, mcname = None):
|
||||||
|
4
lzari.py
Normal file → Executable file
4
lzari.py
Normal file → Executable file
@ -11,7 +11,7 @@ a two level dicitionary look up during compression rather than
|
|||||||
LZARI.C's binary search tree.
|
LZARI.C's binary search tree.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_SCCS_ID = "@(#) mysc lzari.py 1.5 08/02/05 16:00:34\n"
|
_SCCS_ID = "@(#) mysc lzari.py 1.6 12/10/04 19:07:53\n"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import array
|
import array
|
||||||
@ -655,6 +655,8 @@ else:
|
|||||||
# print r, compressed.value, comp_len
|
# print r, compressed.value, comp_len
|
||||||
if r == -1:
|
if r == -1:
|
||||||
raise MemoryError, "out of memory during compression"
|
raise MemoryError, "out of memory during compression"
|
||||||
|
if compressed.value == None:
|
||||||
|
return ""
|
||||||
ret = ctypes.string_at(compressed.value, comp_len.value)
|
ret = ctypes.string_at(compressed.value, comp_len.value)
|
||||||
mylzari_free_encoded(compressed)
|
mylzari_free_encoded(compressed)
|
||||||
return ret;
|
return ret;
|
||||||
|
10
mymc.py
Normal file → Executable file
10
mymc.py
Normal file → Executable file
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
"""A utility for manipulating PS2 memory card images."""
|
"""A utility for manipulating PS2 memory card images."""
|
||||||
|
|
||||||
_SCCS_ID = "@(#) mysc mymc.py 1.11 08/08/11 14:12:26\n"[:-1]
|
_SCCS_ID = "@(#) mysc mymc.py 1.12 12/10/04 19:09:16\n"[:-1]
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
@ -323,7 +323,7 @@ def do_setmode(cmd, mc, opts, args, opterr):
|
|||||||
ent = mc.get_dirent(arg)
|
ent = mc.get_dirent(arg)
|
||||||
if value == None:
|
if value == None:
|
||||||
ent[0] = (ent[0] & clear_mask) | set_mask
|
ent[0] = (ent[0] & clear_mask) | set_mask
|
||||||
print "new %04x" % ent[0]
|
# print "new %04x" % ent[0]
|
||||||
else:
|
else:
|
||||||
ent[0] = value
|
ent[0] = value
|
||||||
mc.set_dirent(arg, ent)
|
mc.set_dirent(arg, ent)
|
||||||
@ -427,7 +427,7 @@ def do_format(cmd, mcname, opts, args, opterr):
|
|||||||
pages_per_cluster = (ps2mc.PS2MC_CLUSTER_SIZE
|
pages_per_cluster = (ps2mc.PS2MC_CLUSTER_SIZE
|
||||||
/ ps2mc.PS2MC_STANDARD_PAGE_SIZE)
|
/ ps2mc.PS2MC_STANDARD_PAGE_SIZE)
|
||||||
pages_per_card = opts.clusters * pages_per_cluster
|
pages_per_card = opts.clusters * pages_per_cluster
|
||||||
params = (True,
|
params = (not opts.no_ecc,
|
||||||
ps2mc.PS2MC_STANDARD_PAGE_SIZE,
|
ps2mc.PS2MC_STANDARD_PAGE_SIZE,
|
||||||
ps2mc.PS2MC_STANDARD_PAGES_PER_ERASE_BLOCK,
|
ps2mc.PS2MC_STANDARD_PAGES_PER_ERASE_BLOCK,
|
||||||
pages_per_card)
|
pages_per_card)
|
||||||
@ -632,7 +632,9 @@ cmd_table = {
|
|||||||
[opt("-c", "--clusters", type="int",
|
[opt("-c", "--clusters", type="int",
|
||||||
help = "Size in clusters of the memory card."),
|
help = "Size in clusters of the memory card."),
|
||||||
opt("-f", "--overwrite-existing", action="store_true",
|
opt("-f", "--overwrite-existing", action="store_true",
|
||||||
help = "Overwrite any existing file")]),
|
help = "Overwrite any existing file"),
|
||||||
|
opt("-e", "--no-ecc", action="store_true",
|
||||||
|
help = "Create an image without ECC")]),
|
||||||
"gui": (do_gui, None,
|
"gui": (do_gui, None,
|
||||||
"",
|
"",
|
||||||
"Starts the graphical user interface.",
|
"Starts the graphical user interface.",
|
||||||
|
50
ps2mc.py
Normal file → Executable file
50
ps2mc.py
Normal file → Executable file
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
"""Manipulate PS2 memory card images."""
|
"""Manipulate PS2 memory card images."""
|
||||||
|
|
||||||
_SCCS_ID = "@(#) mysc ps2mc.py 1.9 08/08/13 15:31:32\n"
|
_SCCS_ID = "@(#) mysc ps2mc.py 1.10 12/10/04 19:10:35\n"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import array
|
import array
|
||||||
@ -62,6 +62,11 @@ class dir_not_found(io_error):
|
|||||||
io_error.__init__(self, ENOENT, "directory not found",
|
io_error.__init__(self, ENOENT, "directory not found",
|
||||||
filename)
|
filename)
|
||||||
|
|
||||||
|
class dir_index_not_found(io_error, IndexError):
|
||||||
|
def __init__(self, filename, index):
|
||||||
|
msg = "index (%d) past of end of directory" % index
|
||||||
|
io_error.__init__(self, ENOENT, msg, filename)
|
||||||
|
|
||||||
class corrupt(io_error):
|
class corrupt(io_error):
|
||||||
def __init__(self, msg, f = None):
|
def __init__(self, msg, f = None):
|
||||||
filename = None
|
filename = None
|
||||||
@ -521,8 +526,8 @@ class ps2mc_directory(object):
|
|||||||
# print "@@@ getitem", index, self.f.name
|
# print "@@@ getitem", index, self.f.name
|
||||||
self.seek(index)
|
self.seek(index)
|
||||||
dirent = self.f.read(PS2MC_DIRENT_LENGTH)
|
dirent = self.f.read(PS2MC_DIRENT_LENGTH)
|
||||||
if dirent == "":
|
if len(dirent) != PS2MC_DIRENT_LENGTH:
|
||||||
raise IndexError
|
raise dir_index_not_found(self.f.name, index)
|
||||||
return unpack_dirent(dirent)
|
return unpack_dirent(dirent)
|
||||||
|
|
||||||
def __setitem__(self, index, new_ent):
|
def __setitem__(self, index, new_ent):
|
||||||
@ -624,20 +629,21 @@ class ps2mc(object):
|
|||||||
self.good_block2 = sb[11]
|
self.good_block2 = sb[11]
|
||||||
self.indirect_fat_cluster_list = sb[12]
|
self.indirect_fat_cluster_list = sb[12]
|
||||||
self.bad_erase_block_list = sb[13]
|
self.bad_erase_block_list = sb[13]
|
||||||
|
|
||||||
self._calculate_derived()
|
self._calculate_derived()
|
||||||
|
|
||||||
self.f = f
|
self.f = f
|
||||||
|
self.ignore_ecc = False
|
||||||
|
|
||||||
self.ignore_ecc = False
|
try:
|
||||||
try:
|
self.read_page(0)
|
||||||
self.read_page(0)
|
self.ignore_ecc = ignore_ecc
|
||||||
self.ignore_ecc = ignore_ecc
|
except ecc_error:
|
||||||
except ecc_error:
|
# the error might be due the fact the file
|
||||||
# the error might be due the fact the file image
|
# image doesn't contain ECC data
|
||||||
# doesn't contain ECC data
|
self.spare_size = 0
|
||||||
self.spare_size = 0
|
self.raw_page_size = self.page_size
|
||||||
self.raw_page_size = self.page_size
|
ignore_ecc = True
|
||||||
ignore_ecc = True
|
|
||||||
|
|
||||||
# sanity check
|
# sanity check
|
||||||
root = self._directory(None, 0, 1)
|
root = self._directory(None, 0, 1)
|
||||||
@ -853,7 +859,11 @@ class ps2mc(object):
|
|||||||
cluster_size = self.cluster_size
|
cluster_size = self.cluster_size
|
||||||
if self.spare_size == 0:
|
if self.spare_size == 0:
|
||||||
self.f.seek(cluster_size * n)
|
self.f.seek(cluster_size * n)
|
||||||
return self.f.write(cluster_size, buf)
|
if len(buf) != cluster_size:
|
||||||
|
raise error, ("internal error: write_cluster:"
|
||||||
|
" %d != %d" % (len(buf),
|
||||||
|
cluster_size))
|
||||||
|
return self.f.write(buf)
|
||||||
n *= pages_per_cluster
|
n *= pages_per_cluster
|
||||||
pgsize = self.page_size
|
pgsize = self.page_size
|
||||||
for i in range(pages_per_cluster):
|
for i in range(pages_per_cluster):
|
||||||
@ -1133,7 +1143,11 @@ class ps2mc(object):
|
|||||||
if start == -1:
|
if start == -1:
|
||||||
start = 0
|
start = 0
|
||||||
for i in range(start, len(dir)) + range(0, start):
|
for i in range(start, len(dir)) + range(0, start):
|
||||||
ent = dir[i]
|
try:
|
||||||
|
ent = dir[i]
|
||||||
|
except IndexError:
|
||||||
|
raise corrupt("Corrupt directory", dir.f)
|
||||||
|
|
||||||
if ent[8] == name and (ent[0] & DF_EXISTS):
|
if ent[8] == name and (ent[0] & DF_EXISTS):
|
||||||
return (i, ent)
|
return (i, ent)
|
||||||
return (None, None)
|
return (None, None)
|
||||||
@ -1800,8 +1814,8 @@ class ps2mc(object):
|
|||||||
self.cluster_size)
|
self.cluster_size)
|
||||||
elif (mode_is_dir(ent[0])
|
elif (mode_is_dir(ent[0])
|
||||||
and ent[8] not in [".", ".."]):
|
and ent[8] not in [".", ".."]):
|
||||||
length += self._dir_size(dirname + "/"
|
length += self.dir_size(dirname + "/"
|
||||||
+ ent[8])
|
+ ent[8])
|
||||||
finally:
|
finally:
|
||||||
dir.close()
|
dir.close()
|
||||||
return length
|
return length
|
||||||
|
5
ps2mc_dir.py
Normal file → Executable file
5
ps2mc_dir.py
Normal file → Executable file
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
"""Functions for working with PS2 memory card directory entries."""
|
"""Functions for working with PS2 memory card directory entries."""
|
||||||
|
|
||||||
_SCCS_ID = "@(#) mysc ps2mc_dir.py 1.3 08/02/05 15:51:58\n"
|
_SCCS_ID = "@(#) mysc ps2mc_dir.py 1.4 12/10/04 19:11:08\n"
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
@ -123,6 +123,9 @@ def tod_now():
|
|||||||
"""Get the current time as a ToD tuple."""
|
"""Get the current time as a ToD tuple."""
|
||||||
return time_to_tod(time.time())
|
return time_to_tod(time.time())
|
||||||
|
|
||||||
|
def tod_from_file(filename):
|
||||||
|
return time_to_tod(os.stat(filename).st_mtime)
|
||||||
|
|
||||||
def mode_is_file(mode):
|
def mode_is_file(mode):
|
||||||
return (mode & (DF_FILE | DF_DIR | DF_EXISTS)) == (DF_FILE | DF_EXISTS)
|
return (mode & (DF_FILE | DF_DIR | DF_EXISTS)) == (DF_FILE | DF_EXISTS)
|
||||||
|
|
||||||
|
0
ps2mc_ecc.py
Normal file → Executable file
0
ps2mc_ecc.py
Normal file → Executable file
29
ps2save.py
Normal file → Executable file
29
ps2save.py
Normal file → Executable file
@ -7,7 +7,7 @@
|
|||||||
# A simple interface for working with various PS2 save file formats.
|
# A simple interface for working with various PS2 save file formats.
|
||||||
#
|
#
|
||||||
|
|
||||||
_SCCS_ID = "@(#) mysc ps2save.py 1.6 08/08/11 14:11:54\n"
|
_SCCS_ID = "@(#) mysc ps2save.py 1.7 12/10/04 19:17:16\n"
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
@ -167,10 +167,10 @@ char_substs = {
|
|||||||
def shift_jis_conv(src, encoding = None):
|
def shift_jis_conv(src, encoding = None):
|
||||||
"""Convert Shift-JIS strings to a graphically similar representation.
|
"""Convert Shift-JIS strings to a graphically similar representation.
|
||||||
|
|
||||||
If encoding is "unicode" then a Unicode string is returned,
|
If encoding is "unicode" then a Unicode string is returned, otherwise
|
||||||
otherwise a string in encoding specified is returned. If necessary,
|
a string in the encoding specified is returned. If necessary,
|
||||||
graphically similar characters are used to replace characters not
|
graphically similar characters are used to replace characters not
|
||||||
exactly representable in the desired encoding.
|
exactly representable in the desired encoding.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if encoding == None:
|
if encoding == None:
|
||||||
@ -272,7 +272,7 @@ class ps2_save_file(object):
|
|||||||
self._compressed = None
|
self._compressed = None
|
||||||
self.file_ents = [None] * ent[2]
|
self.file_ents = [None] * ent[2]
|
||||||
self.file_data = [None] * ent[2]
|
self.file_data = [None] * ent[2]
|
||||||
self.dirent = ent
|
self.dirent = list(ent)
|
||||||
|
|
||||||
def set_file(self, i, ent, data):
|
def set_file(self, i, ent, data):
|
||||||
self.file_ents[i] = ent
|
self.file_ents[i] = ent
|
||||||
@ -344,6 +344,8 @@ class ps2_save_file(object):
|
|||||||
(ent, data) = self.get_file(i)
|
(ent, data) = self.get_file(i)
|
||||||
f.write(pack_dirent(ent))
|
f.write(pack_dirent(ent))
|
||||||
if not mode_is_file(ent[0]):
|
if not mode_is_file(ent[0]):
|
||||||
|
# print ent
|
||||||
|
# print hex(ent[0])
|
||||||
raise error, "Directory has a subdirectory."
|
raise error, "Directory has a subdirectory."
|
||||||
f.write(data)
|
f.write(data)
|
||||||
f.write("\0" * (round_up(len(data), cluster_size)
|
f.write("\0" * (round_up(len(data), cluster_size)
|
||||||
@ -360,7 +362,7 @@ class ps2_save_file(object):
|
|||||||
s = lzari.decode(s, length,
|
s = lzari.decode(s, length,
|
||||||
"decompressing " + self.dirent[8] + ": ")
|
"decompressing " + self.dirent[8] + ": ")
|
||||||
dirlen = self.dirent[2]
|
dirlen = self.dirent[2]
|
||||||
now = tod_now()
|
timestamp = self.dirent[3]
|
||||||
off = 0
|
off = 0
|
||||||
for i in range(dirlen):
|
for i in range(dirlen):
|
||||||
if len(s) - off < 36:
|
if len(s) - off < 36:
|
||||||
@ -373,13 +375,14 @@ class ps2_save_file(object):
|
|||||||
if len(data) != l:
|
if len(data) != l:
|
||||||
raise eof, f
|
raise eof, f
|
||||||
self.set_file(i,
|
self.set_file(i,
|
||||||
(DF_RWX | DF_FILE | DF_0400, 0, l,
|
(DF_RWX | DF_FILE | DF_0400 | DF_EXISTS,
|
||||||
now, 0, 0, now, 0, name),
|
0, l, timestamp, 0, 0, timestamp, 0,
|
||||||
|
name),
|
||||||
data)
|
data)
|
||||||
off += l
|
off += l
|
||||||
off = round_up(off + 8, 16) - 8
|
off = round_up(off + 8, 16) - 8
|
||||||
|
|
||||||
def load_max_drive(self, f):
|
def load_max_drive(self, f, timestamp = None):
|
||||||
s = f.read(0x5C)
|
s = f.read(0x5C)
|
||||||
magic = None
|
magic = None
|
||||||
if len(s) == 0x5C:
|
if len(s) == 0x5C:
|
||||||
@ -394,9 +397,11 @@ class ps2_save_file(object):
|
|||||||
else:
|
else:
|
||||||
s = _read_fixed(f, clen - 4)
|
s = _read_fixed(f, clen - 4)
|
||||||
dirname = zero_terminate(dirname)
|
dirname = zero_terminate(dirname)
|
||||||
now = tod_now()
|
if timestamp == None:
|
||||||
self.set_directory((DF_RWX | DF_DIR | DF_0400, 0,
|
timestamp = tod_now()
|
||||||
dirlen, now, 0, 0, now, 0, dirname),
|
self.set_directory((DF_RWX | DF_DIR | DF_0400 | DF_EXISTS,
|
||||||
|
0, dirlen, timestamp, 0, 0, timestamp, 0,
|
||||||
|
dirname),
|
||||||
True)
|
True)
|
||||||
self._compressed = (length, s)
|
self._compressed = (length, s)
|
||||||
|
|
||||||
|
0
sjistab.py
Normal file → Executable file
0
sjistab.py
Normal file → Executable file
2
verbuild.py
Normal file → Executable file
2
verbuild.py
Normal file → Executable file
@ -1,2 +1,2 @@
|
|||||||
MYMC_VERSION_BUILD = r'''5'''
|
MYMC_VERSION_BUILD = r'''6'''
|
||||||
MYMC_VERSION_MAJOR = r'''2'''
|
MYMC_VERSION_MAJOR = r'''2'''
|
||||||
|
Loading…
Reference in New Issue
Block a user