mirror of
https://github.com/ps2dev/mymc.git
synced 2024-11-24 03:20:10 +01:00
Update sources to 2.7 from author's website
http://www.csclub.uwaterloo.ca:11068/mymc/ -updated to use Python 2.7 and Visual C++ 2008 runtime -add a rename command to the command line interface -a few minor bugs fixed
This commit is contained in:
parent
8cdf72b321
commit
ddfa6a79f9
182
gui.py
182
gui.py
@ -7,13 +7,14 @@
|
||||
|
||||
"""Graphical user-interface for mymc."""
|
||||
|
||||
_SCCS_ID = "@(#) mymc gui.py 1.4 12/10/04 18:51:51\n"
|
||||
_SCCS_ID = "@(#) mymc gui.py 1.8 22/02/05 19:20:59\n"
|
||||
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
import cStringIO
|
||||
import time
|
||||
from functools import partial
|
||||
|
||||
# Work around a problem with mixing wx and py2exe
|
||||
if os.name == "nt" and hasattr(sys, "setdefaultencoding"):
|
||||
@ -26,16 +27,16 @@ import guires
|
||||
|
||||
try:
|
||||
import ctypes
|
||||
import mymcsup
|
||||
D3DXVECTOR3 = mymcsup.D3DXVECTOR3
|
||||
D3DXVECTOR4 = mymcsup.D3DXVECTOR4
|
||||
D3DXVECTOR4_ARRAY3 = mymcsup.D3DXVECTOR4_ARRAY3
|
||||
import mymcicon
|
||||
D3DXVECTOR3 = mymcicon.D3DXVECTOR3
|
||||
D3DXVECTOR4 = mymcicon.D3DXVECTOR4
|
||||
D3DXVECTOR4_ARRAY3 = mymcicon.D3DXVECTOR4_ARRAY3
|
||||
|
||||
def mkvec4arr3(l):
|
||||
return D3DXVECTOR4_ARRAY3(*[D3DXVECTOR4(*vec)
|
||||
for vec in l])
|
||||
except ImportError:
|
||||
mymcsup = None
|
||||
mymcicon = None
|
||||
|
||||
lighting_none = {"lighting": False,
|
||||
"vertex_diffuse": False,
|
||||
@ -89,7 +90,7 @@ camera_near = [0, 3, -6]
|
||||
camera_flat = [0, 2, -7.5]
|
||||
|
||||
def get_dialog_units(win):
|
||||
return win.ConvertDialogPointToPixels((1, 1))[0]
|
||||
return win.ConvertDialogToPixels((1, 1))[0]
|
||||
|
||||
def single_title(title):
|
||||
"""Convert the two parts of an icon.sys title into one string."""
|
||||
@ -105,7 +106,7 @@ def _get_icon_resource_as_images(name):
|
||||
# count = wx.Image_GetImageCount(f, wx.BITMAP_TYPE_ICO)
|
||||
for i in range(count):
|
||||
f.seek(0)
|
||||
images.append(wx.ImageFromStream(f, wx.BITMAP_TYPE_ICO, i))
|
||||
images.append(wx.Image(f, wx.BITMAP_TYPE_ICO, i))
|
||||
return images
|
||||
|
||||
def get_icon_resource(name):
|
||||
@ -113,8 +114,8 @@ def get_icon_resource(name):
|
||||
|
||||
bundle = wx.IconBundle()
|
||||
for img in _get_icon_resource_as_images(name):
|
||||
bmp = wx.BitmapFromImage(img)
|
||||
icon = wx.IconFromBitmap(bmp)
|
||||
bmp = wx.Bitmap(img)
|
||||
icon = wx.Icon(bmp)
|
||||
bundle.AddIcon(icon)
|
||||
return bundle
|
||||
|
||||
@ -128,7 +129,7 @@ def get_icon_resource_bmp(name, size):
|
||||
for img in _get_icon_resource_as_images(name):
|
||||
sz = (img.GetWidth(), img.GetHeight())
|
||||
if sz == size:
|
||||
return wx.BitmapFromImage(img)
|
||||
return wx.Bitmap(img)
|
||||
if sz[0] >= size[0] and sz[1] >= size[1]:
|
||||
if ((best_size[0] < size[0] or best_size[1] < size[1])
|
||||
or sz[0] * sz[1] < best_size[0] * best_size[1]):
|
||||
@ -138,7 +139,7 @@ def get_icon_resource_bmp(name, size):
|
||||
best = img
|
||||
best_size = sz
|
||||
img = best.Rescale(size[0], size[1], wx.IMAGE_QUALITY_HIGH)
|
||||
return wx.BitmapFromImage(img)
|
||||
return wx.Bitmap(img)
|
||||
|
||||
|
||||
class dirlist_control(wx.ListCtrl):
|
||||
@ -150,10 +151,11 @@ class dirlist_control(wx.ListCtrl):
|
||||
self.evt_select = evt_select
|
||||
wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
|
||||
style = wx.LC_REPORT)
|
||||
wx.EVT_LIST_COL_CLICK(self, -1, self.evt_col_click)
|
||||
wx.EVT_LIST_ITEM_FOCUSED(self, -1, evt_focus)
|
||||
wx.EVT_LIST_ITEM_SELECTED(self, -1, self.evt_item_selected)
|
||||
wx.EVT_LIST_ITEM_DESELECTED(self, -1, self.evt_item_deselected)
|
||||
self.Bind(wx.EVT_LIST_COL_CLICK, self.evt_col_click)
|
||||
self.Bind(wx.EVT_LIST_ITEM_FOCUSED, evt_focus)
|
||||
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.evt_item_selected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_DESELECTED,
|
||||
self.evt_item_deselected)
|
||||
|
||||
def _update_dirtable(self, mc, dir):
|
||||
self.dirtable = table = []
|
||||
@ -182,33 +184,42 @@ class dirlist_control(wx.ListCtrl):
|
||||
finally:
|
||||
dir.close()
|
||||
|
||||
def cmp_dir_name(self, i1, i2):
|
||||
return self.dirtable[i1][0][8] > self.dirtable[i2][0][8]
|
||||
def get_dir_name(self, i):
|
||||
return self.dirtable[i][0][8]
|
||||
|
||||
def cmp_dir_title(self, i1, i2):
|
||||
return self.dirtable[i1][3] > self.dirtable[i2][3]
|
||||
def get_dir_title(self, i):
|
||||
return self.dirtable[i][3]
|
||||
|
||||
def cmp_dir_size(self, i1, i2):
|
||||
return self.dirtable[i1][2] > self.dirtable[i2][2]
|
||||
def get_dir_size(self, i):
|
||||
return self.dirtable[i][2]
|
||||
|
||||
def cmp_dir_modified(self, i1, i2):
|
||||
m1 = list(self.dirtable[i1][0][6])
|
||||
m2 = list(self.dirtable[i2][0][6])
|
||||
m1.reverse()
|
||||
m2.reverse()
|
||||
return m1 > m2
|
||||
def get_dir_modified(self, i):
|
||||
m = list(self.dirtable[i][0][6])
|
||||
m.reverse()
|
||||
return m
|
||||
|
||||
def sort_items(self, key):
|
||||
def cmp(i1, i2):
|
||||
a1 = key(i1)
|
||||
a2 = key(i2)
|
||||
if a1 < a2:
|
||||
return -1
|
||||
if a1 > a2:
|
||||
return 1
|
||||
return 0
|
||||
self.SortItems(cmp)
|
||||
|
||||
def evt_col_click(self, event):
|
||||
col = event.m_col
|
||||
col = event.GetColumn()
|
||||
if col == 0:
|
||||
cmp = self.cmp_dir_name
|
||||
key = self.get_dir_name
|
||||
elif col == 1:
|
||||
cmp = self.cmp_dir_size
|
||||
key = self.get_dir_size
|
||||
elif col == 2:
|
||||
cmp = self.cmp_dir_modified
|
||||
key = self.get_dir_modified
|
||||
elif col == 3:
|
||||
cmp = self.cmp_dir_title
|
||||
self.SortItems(cmp)
|
||||
key = self.get_dir_title
|
||||
self.sort_items(key)
|
||||
return
|
||||
|
||||
def evt_item_selected(self, event):
|
||||
@ -236,34 +247,33 @@ class dirlist_control(wx.ListCtrl):
|
||||
|
||||
self.update_dirtable(mc)
|
||||
|
||||
empty = len(self.dirtable) == 0
|
||||
empty = (len(self.dirtable) == 0)
|
||||
self.Enable(not empty)
|
||||
if empty:
|
||||
return
|
||||
|
||||
for (i, a) in enumerate(self.dirtable):
|
||||
(ent, icon_sys, size, title) = a
|
||||
li = self.InsertStringItem(i, ent[8])
|
||||
self.SetStringItem(li, 1, "%dK" % (size / 1024))
|
||||
li = self.InsertItem(i, ent[8])
|
||||
self.SetItem(li, 1, "%dK" % (size / 1024))
|
||||
m = ent[6]
|
||||
m = ("%04d-%02d-%02d %02d:%02d"
|
||||
% (m[5], m[4], m[3], m[2], m[1]))
|
||||
self.SetStringItem(li, 2, m)
|
||||
self.SetStringItem(li, 3, single_title(title))
|
||||
self.SetItem(li, 2, ("%04d-%02d-%02d %02d:%02d"
|
||||
% (m[5], m[4], m[3], m[2], m[1])))
|
||||
self.SetItem(li, 3, single_title(title))
|
||||
self.SetItemData(li, i)
|
||||
|
||||
du = get_dialog_units(self)
|
||||
for i in range(4):
|
||||
self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
|
||||
self.SetColumnWidth(i, self.GetColumnWidth(i) + du)
|
||||
self.SortItems(self.cmp_dir_name)
|
||||
self.sort_items(self.get_dir_name)
|
||||
|
||||
|
||||
class icon_window(wx.Window):
|
||||
"""Displays a save file's 3D icon. Windows only.
|
||||
|
||||
The rendering of the 3D icon is handled by C++ code in the
|
||||
mymcsup DLL which subclasses this window. This class mainly
|
||||
mymcicon DLL which subclasses this window. This class mainly
|
||||
handles configuration options that affect how the 3D icon is
|
||||
displayed.
|
||||
"""
|
||||
@ -310,40 +320,38 @@ class icon_window(wx.Window):
|
||||
menu.AppendRadioItem(icon_window.ID_CMD_CAMERA_HIGH,
|
||||
"Camera High")
|
||||
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_ANIMATE,
|
||||
self.evt_menu_animate)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_LIGHT_NONE,
|
||||
self.evt_menu_light)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_LIGHT_ICON,
|
||||
self.evt_menu_light)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_LIGHT_ALT1,
|
||||
self.evt_menu_light)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_LIGHT_ALT2,
|
||||
self.evt_menu_light)
|
||||
bind_menu = partial(win.Bind, wx.EVT_MENU)
|
||||
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_CAMERA_FLAT,
|
||||
self.evt_menu_camera)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_CAMERA_DEFAULT,
|
||||
self.evt_menu_camera)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_CAMERA_NEAR,
|
||||
self.evt_menu_camera)
|
||||
wx.EVT_MENU(win, icon_window.ID_CMD_CAMERA_HIGH,
|
||||
self.evt_menu_camera)
|
||||
bind_menu(self.evt_menu_animate, None,
|
||||
icon_window.ID_CMD_ANIMATE)
|
||||
|
||||
bind_menu_light = partial(bind_menu, self.evt_menu_light, None)
|
||||
bind_menu_light(icon_window.ID_CMD_LIGHT_NONE)
|
||||
bind_menu_light(icon_window.ID_CMD_LIGHT_ICON)
|
||||
bind_menu_light(icon_window.ID_CMD_LIGHT_ALT1)
|
||||
bind_menu_light(icon_window.ID_CMD_LIGHT_ALT2)
|
||||
|
||||
bind_menu_camera = partial(bind_menu,
|
||||
self.evt_menu_camera, None)
|
||||
bind_menu_camera(icon_window.ID_CMD_CAMERA_FLAT)
|
||||
bind_menu_camera(icon_window.ID_CMD_CAMERA_DEFAULT)
|
||||
bind_menu_camera(icon_window.ID_CMD_CAMERA_NEAR)
|
||||
bind_menu_camera(icon_window.ID_CMD_CAMERA_HIGH)
|
||||
|
||||
def __init__(self, parent, focus):
|
||||
self.failed = False
|
||||
wx.Window.__init__(self, parent)
|
||||
if mymcsup == None:
|
||||
if mymcicon == None:
|
||||
self.failed = True
|
||||
return
|
||||
r = mymcsup.init_icon_renderer(focus.GetHandle(),
|
||||
r = mymcicon.init_icon_renderer(focus.GetHandle(),
|
||||
self.GetHandle())
|
||||
if r == -1:
|
||||
print "init_icon_renderer failed"
|
||||
self.failed = True
|
||||
return
|
||||
|
||||
self.config = config = mymcsup.icon_config()
|
||||
self.config = config = mymcicon.icon_config()
|
||||
config.animate = True
|
||||
|
||||
self.menu = wx.Menu()
|
||||
@ -351,11 +359,11 @@ class icon_window(wx.Window):
|
||||
self.set_lighting(self.ID_CMD_LIGHT_ALT2)
|
||||
self.set_camera(self.ID_CMD_CAMERA_DEFAULT)
|
||||
|
||||
wx.EVT_CONTEXT_MENU(self, self.evt_context_menu)
|
||||
self.Bind(wx.EVT_CONTEXT_MENU, self.evt_context_menu)
|
||||
|
||||
def __del__(self):
|
||||
if mymcsup != None:
|
||||
mymcsup.delete_icon_renderer()
|
||||
if mymcicon != None:
|
||||
mymcicon.delete_icon_renderer()
|
||||
|
||||
def update_menu(self, menu):
|
||||
"""Update the content menu according to the current config."""
|
||||
@ -371,9 +379,9 @@ class icon_window(wx.Window):
|
||||
return
|
||||
|
||||
if icon_sys == None or icon == None:
|
||||
r = mymcsup.load_icon(None, 0, None, 0)
|
||||
r = mymcicon.load_icon(None, 0, None, 0)
|
||||
else:
|
||||
r = mymcsup.load_icon(icon_sys, len(icon_sys),
|
||||
r = mymcicon.load_icon(icon_sys, len(icon_sys),
|
||||
icon, len(icon))
|
||||
if r != 0:
|
||||
print "load_icon", r
|
||||
@ -390,7 +398,7 @@ class icon_window(wx.Window):
|
||||
config.light_dirs = mkvec4arr3(light_dirs)
|
||||
config.light_colours = mkvec4arr3(light_colours)
|
||||
config.ambient = D3DXVECTOR4(*ambient)
|
||||
if mymcsup.set_config(config) == -1:
|
||||
if mymcicon.set_config(config) == -1:
|
||||
self.failed = True
|
||||
|
||||
def set_lighting(self, id):
|
||||
@ -401,14 +409,14 @@ class icon_window(wx.Window):
|
||||
if self.failed:
|
||||
return
|
||||
self.config.animate = animate
|
||||
if mymcsup.set_config(self.config) == -1:
|
||||
if mymcicon.set_config(self.config) == -1:
|
||||
self.failed = True
|
||||
|
||||
def _set_camera(self, camera):
|
||||
if self.failed:
|
||||
return
|
||||
self.config.camera = mymcsup.D3DXVECTOR3(*camera)
|
||||
if mymcsup.set_config(self.config) == -1:
|
||||
self.config.camera = mymcicon.D3DXVECTOR3(*camera)
|
||||
if mymcicon.set_config(self.config) == -1:
|
||||
self.failed = True
|
||||
|
||||
def set_camera(self, id):
|
||||
@ -460,7 +468,7 @@ class gui_config(wx.Config):
|
||||
def add_tool(toolbar, id, label, ico):
|
||||
tbsize = toolbar.GetToolBitmapSize()
|
||||
bmp = get_icon_resource_bmp(ico, tbsize)
|
||||
return toolbar.AddLabelTool(id, label, bmp, shortHelp = label)
|
||||
return toolbar.AddTool(id, label, bmp, shortHelp = label)
|
||||
|
||||
class gui_frame(wx.Frame):
|
||||
"""The main top level window."""
|
||||
@ -502,23 +510,25 @@ class gui_frame(wx.Frame):
|
||||
self.icon_win = None
|
||||
|
||||
size = (750, 350)
|
||||
if mymcsup == None:
|
||||
if mymcicon == None:
|
||||
size = (500, 350)
|
||||
wx.Frame.__init__(self, parent, wx.ID_ANY, title, size = size)
|
||||
|
||||
wx.EVT_CLOSE(self, self.evt_close)
|
||||
self.Bind(wx.EVT_CLOSE, self.evt_close)
|
||||
|
||||
self.config = gui_config()
|
||||
self.title = title
|
||||
|
||||
self.SetIcons(get_icon_resource("mc4.ico"))
|
||||
|
||||
wx.EVT_MENU(self, self.ID_CMD_EXIT, self.evt_cmd_exit)
|
||||
wx.EVT_MENU(self, self.ID_CMD_OPEN, self.evt_cmd_open)
|
||||
wx.EVT_MENU(self, self.ID_CMD_EXPORT, self.evt_cmd_export)
|
||||
wx.EVT_MENU(self, self.ID_CMD_IMPORT, self.evt_cmd_import)
|
||||
wx.EVT_MENU(self, self.ID_CMD_DELETE, self.evt_cmd_delete)
|
||||
wx.EVT_MENU(self, self.ID_CMD_ASCII, self.evt_cmd_ascii)
|
||||
bind_menu = (lambda handler, id:
|
||||
self.Bind(wx.EVT_MENU, handler, None, id))
|
||||
bind_menu(self.evt_cmd_exit, self.ID_CMD_EXIT)
|
||||
bind_menu(self.evt_cmd_open, self.ID_CMD_OPEN)
|
||||
bind_menu(self.evt_cmd_export, self.ID_CMD_EXPORT)
|
||||
bind_menu(self.evt_cmd_import, self.ID_CMD_IMPORT)
|
||||
bind_menu(self.evt_cmd_delete, self.ID_CMD_DELETE)
|
||||
bind_menu(self.evt_cmd_ascii, self.ID_CMD_ASCII, )
|
||||
|
||||
filemenu = wx.Menu()
|
||||
filemenu.Append(self.ID_CMD_OPEN, "&Open...",
|
||||
@ -541,7 +551,7 @@ class gui_frame(wx.Frame):
|
||||
"Show descriptions in ASCII instead of Shift-JIS")
|
||||
|
||||
|
||||
wx.EVT_MENU_OPEN(self, self.evt_menu_open);
|
||||
self.Bind(wx.EVT_MENU_OPEN, self.evt_menu_open);
|
||||
|
||||
self.CreateToolBar(wx.TB_HORIZONTAL)
|
||||
self.toolbar = toolbar = self.GetToolBar()
|
||||
@ -554,7 +564,7 @@ class gui_frame(wx.Frame):
|
||||
toolbar.Realize()
|
||||
|
||||
self.statusbar = self.CreateStatusBar(2,
|
||||
style = wx.ST_SIZEGRIP)
|
||||
style = wx.STB_SIZEGRIP)
|
||||
self.statusbar.SetStatusWidths([-2, -1])
|
||||
|
||||
panel = wx.Panel(self, wx.ID_ANY, (0, 0))
|
||||
@ -573,7 +583,7 @@ class gui_frame(wx.Frame):
|
||||
sizer.AddSpacer(5)
|
||||
|
||||
icon_win = None
|
||||
if mymcsup != None:
|
||||
if mymcicon != None:
|
||||
icon_win = icon_window(panel, self)
|
||||
if icon_win.failed:
|
||||
icon_win.Destroy()
|
||||
@ -914,7 +924,7 @@ class gui_frame(wx.Frame):
|
||||
def run(filename = None):
|
||||
"""Display a GUI for working with memory card images."""
|
||||
|
||||
wx_app = wx.PySimpleApp()
|
||||
wx_app = wx.App()
|
||||
frame = gui_frame(None, "mymc", filename)
|
||||
return wx_app.MainLoop()
|
||||
|
||||
|
2
lzari.py
2
lzari.py
@ -11,7 +11,7 @@ a two level dicitionary look up during compression rather than
|
||||
LZARI.C's binary search tree.
|
||||
"""
|
||||
|
||||
_SCCS_ID = "@(#) mysc lzari.py 1.6 12/10/04 19:07:53\n"
|
||||
_SCCS_ID = "@(#) mymc lzari.py 1.6 12/10/04 19:07:53\n"
|
||||
|
||||
import sys
|
||||
import array
|
||||
|
17
mymc.py
17
mymc.py
@ -7,7 +7,7 @@
|
||||
|
||||
"""A utility for manipulating PS2 memory card images."""
|
||||
|
||||
_SCCS_ID = "@(#) mysc mymc.py 1.12 12/10/04 19:09:16\n"[:-1]
|
||||
_SCCS_ID = "@(#) mymc mymc.py 1.13 22/01/15 01:04:45\n"[:-1]
|
||||
|
||||
import sys
|
||||
import os
|
||||
@ -18,6 +18,9 @@ import binascii
|
||||
import string
|
||||
from errno import EEXIST, EIO
|
||||
|
||||
#import gc
|
||||
#gc.set_debug(gc.DEBUG_LEAK)
|
||||
|
||||
import ps2mc
|
||||
import ps2save
|
||||
from ps2mc_dir import *
|
||||
@ -328,6 +331,11 @@ def do_setmode(cmd, mc, opts, args, opterr):
|
||||
ent[0] = value
|
||||
mc.set_dirent(arg, ent)
|
||||
|
||||
def do_rename(cmd, mc, opts, args, opterr):
|
||||
if len(args) != 2:
|
||||
opterr("Old and new names required")
|
||||
mc.rename(args[0], args[1])
|
||||
|
||||
def _get_ps2_title(mc, enc):
|
||||
s = mc.get_icon_sys(".");
|
||||
if s == None:
|
||||
@ -549,7 +557,7 @@ cmd_table = {
|
||||
"Import save files into the memory card.",
|
||||
[opt("-i", "--ignore-existing", action="store_true",
|
||||
help = ("Ignore files that already exist"
|
||||
"on the image.")),
|
||||
" on the image.")),
|
||||
opt("-d", "--directory", metavar="DEST",
|
||||
help = 'Import to "DEST".')]),
|
||||
"export": (do_export, "rb",
|
||||
@ -614,6 +622,10 @@ cmd_table = {
|
||||
help = "Clear executable flag"),
|
||||
opt("-X", dest="hex_value", default=None,
|
||||
help = optparse.SUPPRESS_HELP)]),
|
||||
"rename": (do_rename, "r+b",
|
||||
"oldname newname",
|
||||
"Rename a file or directory",
|
||||
[]),
|
||||
"dir": (do_dir, "rb",
|
||||
None,
|
||||
"Display save file information.",
|
||||
@ -731,6 +743,7 @@ def main():
|
||||
except ImportError:
|
||||
gui = None
|
||||
if gui != None:
|
||||
optparser.destroy()
|
||||
gui.run()
|
||||
sys.exit(0)
|
||||
|
||||
|
280
ps2mc.py
280
ps2mc.py
@ -7,13 +7,13 @@
|
||||
|
||||
"""Manipulate PS2 memory card images."""
|
||||
|
||||
_SCCS_ID = "@(#) mysc ps2mc.py 1.10 12/10/04 19:10:35\n"
|
||||
_SCCS_ID = "@(#) mymc ps2mc.py 1.11 22/01/15 01:17:07\n"
|
||||
|
||||
import sys
|
||||
import array
|
||||
import struct
|
||||
from errno import EACCES, ENOENT, EEXIST, ENOTDIR, EISDIR, EROFS, ENOTEMPTY,\
|
||||
ENOSPC, EIO, EBUSY
|
||||
ENOSPC, EIO, EBUSY, EINVAL
|
||||
import fnmatch
|
||||
import traceback
|
||||
|
||||
@ -82,6 +82,7 @@ if sys.byteorder == "big":
|
||||
def unpack_32bit_array(s):
|
||||
a = array.array('I', s)
|
||||
a.byteswap()
|
||||
return a
|
||||
|
||||
def pack_32bit_array(a):
|
||||
a = a[:]
|
||||
@ -114,6 +115,16 @@ def pack_superblock(sb):
|
||||
unpack_fat = unpack_32bit_array
|
||||
pack_fat = pack_32bit_array
|
||||
|
||||
def pathname_split(pathname):
|
||||
if pathname == "":
|
||||
return (None, False, False)
|
||||
components = pathname.split("/")
|
||||
return ([name
|
||||
for name in components
|
||||
if name != ""],
|
||||
components[0] != "",
|
||||
components[-1] == "")
|
||||
|
||||
class lru_cache(object):
|
||||
def __init__(self, length):
|
||||
self._lru_list = [[i - 1, None, None, i + 1]
|
||||
@ -539,14 +550,9 @@ class ps2mc_directory(object):
|
||||
mode = ((new_ent[0] & ~(DF_FILE | DF_DIR | DF_EXISTS))
|
||||
| (mode & (DF_FILE | DF_DIR | DF_EXISTS)))
|
||||
ent[0] = mode
|
||||
if new_ent[1] != None:
|
||||
ent[1] = new_ent[1]
|
||||
if new_ent[3] != None:
|
||||
ent[3] = new_ent[3]
|
||||
if new_ent[6] != None:
|
||||
ent[6] = new_ent[6]
|
||||
if new_ent[7] != None:
|
||||
ent[7] = new_ent[7]
|
||||
for i in [1, 3, 6, 7, 8]: # ???, created, modifed, attr
|
||||
if new_ent[i] != None:
|
||||
ent[i] = new_ent[i]
|
||||
self.write_raw_ent(index, ent, False)
|
||||
|
||||
def close(self):
|
||||
@ -1155,6 +1161,9 @@ class ps2mc(object):
|
||||
def create_dir_entry(self, parent_dirloc, name, mode):
|
||||
"""Create a new directory entry in a directory."""
|
||||
|
||||
if name == "":
|
||||
raise file_not_found, name
|
||||
|
||||
# print "@@@ create_dir_ent", parent_dirloc, name
|
||||
dir_ent = self._dirloc_to_ent(parent_dirloc)
|
||||
dir = self._directory(parent_dirloc, dir_ent[4], dir_ent[2],
|
||||
@ -1262,49 +1271,54 @@ class ps2mc(object):
|
||||
directory, if it exists, otherwise it's the dirloc the
|
||||
pathname's parent directory, if that exists otherwise
|
||||
it's None. The second component is directory entry
|
||||
for pathname if it exists, otherwise None. The third
|
||||
for pathname if it exists, otherwise its dummy entry
|
||||
with the first element set to 0, and the last element
|
||||
set to the final component of the pathname. The third
|
||||
is a boolean value that's true if the pathname refers
|
||||
a directory."""
|
||||
|
||||
components = pathname.split("/")
|
||||
if len(components) < 1:
|
||||
# could return curdir
|
||||
# print "@@@ path_search", repr(pathname)
|
||||
if pathname == "":
|
||||
return (None, None, False)
|
||||
|
||||
dirloc = self.curdir
|
||||
if components[0] == "":
|
||||
dirloc = (0, 0)
|
||||
(components, relative, is_dir) = pathname_split(pathname)
|
||||
|
||||
dirloc = (0, 0)
|
||||
if relative:
|
||||
dirloc = self.curdir
|
||||
|
||||
tmpname = "<path_search temp>"
|
||||
_directory = self._directory
|
||||
|
||||
if dirloc == (0, 0):
|
||||
rootent = self.read_allocatable_cluster(0)
|
||||
ent = unpack_dirent(rootent[:PS2MC_DIRENT_LENGTH])
|
||||
dir_cluster = 0
|
||||
dir = self._directory(dirloc, dir_cluster, ent[2],
|
||||
name = "<path_search temp>")
|
||||
dir = _directory(dirloc, dir_cluster, ent[2],
|
||||
name = tmpname)
|
||||
else:
|
||||
ent = self._dirloc_to_ent(dirloc)
|
||||
dir = self._directory(dirloc, ent[4], ent[2],
|
||||
name = "<path_search temp>")
|
||||
dir = _directory(dirloc, ent[4], ent[2],
|
||||
name = tmpname)
|
||||
|
||||
for s in components:
|
||||
# print "@@@", dirloc, repr(s), dir == None, ent
|
||||
if s == "":
|
||||
continue
|
||||
|
||||
if dir == None:
|
||||
# tried to traverse a file or a
|
||||
# non-existent directory
|
||||
return (None, None, False)
|
||||
return (None, (0, 0, 0, 0, 0, 0, 0, 0, None),
|
||||
False)
|
||||
|
||||
if s == "" or s == ".":
|
||||
if s == ".":
|
||||
continue
|
||||
if s == "..":
|
||||
dotent = dir[0]
|
||||
dir.close()
|
||||
dirloc = (dotent[4], dotent[5])
|
||||
ent = self._dirloc_to_ent(dirloc)
|
||||
dir = self._directory(dirloc, ent[4], ent[2],
|
||||
name
|
||||
= "<path_search temp>")
|
||||
dir = _directory(dirloc, ent[4], ent[2],
|
||||
name = tmpname)
|
||||
continue
|
||||
|
||||
dir_cluster = ent[4]
|
||||
@ -1317,29 +1331,34 @@ class ps2mc(object):
|
||||
|
||||
dirloc = (dir_cluster, i)
|
||||
if ent[0] & DF_DIR:
|
||||
dir = self._directory(dirloc, ent[4], ent[2],
|
||||
name
|
||||
= "<path_search temp>")
|
||||
dir = _directory(dirloc, ent[4], ent[2],
|
||||
name = tmpname)
|
||||
|
||||
if dir != None:
|
||||
dir.close()
|
||||
is_dir = True
|
||||
elif ent != None:
|
||||
is_dir = False
|
||||
|
||||
return (dirloc, ent, dir != None)
|
||||
if ent == None:
|
||||
ent = (0, 0, 0, 0, 0, 0, 0, 0, components[-1])
|
||||
|
||||
return (dirloc, ent, is_dir)
|
||||
|
||||
def open(self, filename, mode = "r"):
|
||||
"""Open a file, returning a new file-like object for it."""
|
||||
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
# print "@@@ open", (dirloc, ent)
|
||||
if dirloc == None or (ent == None and is_dir):
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if is_dir:
|
||||
raise io_error, (EISDIR, "not a regular file",
|
||||
filename)
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
if mode[0] not in "wa":
|
||||
raise file_not_found, filename
|
||||
name = filename.split("/")[-1]
|
||||
name = ent[8]
|
||||
(dirloc, ent) = self.create_dir_entry(dirloc, name,
|
||||
DF_FILE | DF_RWX
|
||||
| DF_0400);
|
||||
@ -1354,7 +1373,7 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
raise dir_not_found, filename
|
||||
if not is_dir:
|
||||
raise io_error, (ENOTDIR, "not a directory", filename)
|
||||
@ -1364,12 +1383,9 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if ent != None:
|
||||
if ent[0] != 0:
|
||||
raise io_error, (EEXIST, "directory exists", filename)
|
||||
a = filename.split("/")
|
||||
name = a.pop()
|
||||
while name == "":
|
||||
name = a.pop()
|
||||
name = ent[8]
|
||||
self.create_dir_entry(dirloc, name, DF_DIR | DF_RWX | DF_0400)
|
||||
self.flush()
|
||||
|
||||
@ -1392,7 +1408,7 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
raise file_not_found, filename
|
||||
if is_dir:
|
||||
if ent[4] == 0:
|
||||
@ -1410,7 +1426,7 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
raise dir_not_found, filename
|
||||
if not is_dir:
|
||||
raise io_error, (ENOTDIR, "not a directory", filename)
|
||||
@ -1423,7 +1439,7 @@ class ps2mc(object):
|
||||
throwing a error."""
|
||||
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
return None
|
||||
return ent[0]
|
||||
|
||||
@ -1433,7 +1449,7 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
raise file_not_found, filename
|
||||
return ent
|
||||
|
||||
@ -1446,16 +1462,101 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(filename)
|
||||
if dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
raise file_not_found, filename
|
||||
dir = self._opendir_parent_dirloc(dirloc)
|
||||
dir = self._opendir_parent_dirloc(dirloc, "r+b")
|
||||
try:
|
||||
new_ent = list(new_ent)
|
||||
new_ent[8] = None
|
||||
dir[dirloc[1]] = new_ent
|
||||
finally:
|
||||
dir.close()
|
||||
self.flush()
|
||||
return ent
|
||||
|
||||
def is_ancestor(self, dirloc, olddirloc):
|
||||
while True:
|
||||
if dirloc == olddirloc:
|
||||
return True
|
||||
if dirloc == (0, 0):
|
||||
return False
|
||||
dirloc = self._get_parent_dirloc(dirloc)
|
||||
|
||||
def rename(self, oldpathname, newpathname):
|
||||
(olddirloc, oldent, is_dir) = self.path_search(oldpathname)
|
||||
if olddirloc == None:
|
||||
raise path_not_found, oldpathname
|
||||
if oldent[0] == 0:
|
||||
raise file_not_found, oldpathname
|
||||
|
||||
if olddirloc == (0, 0):
|
||||
raise io_error, (EINVAL,
|
||||
"cannot rename root directory",
|
||||
oldpathname)
|
||||
if olddirloc in self.open_files:
|
||||
raise io_error, (EBUSY, "cannot rename open file",
|
||||
newname)
|
||||
|
||||
(newparentdirloc, newent, x) = self.path_search(newpathname)
|
||||
if newparentdirloc == None:
|
||||
raise path_not_found, newpathname
|
||||
if newent[0] != 0:
|
||||
raise io_error, (EEXIST, "file exists", newpathname)
|
||||
newname = newent[8]
|
||||
|
||||
oldparentdirloc = self._get_parent_dirloc(olddirloc)
|
||||
if oldparentdirloc == newparentdirloc:
|
||||
dir = self._opendir_dirloc(oldparentdirloc, "r+b")
|
||||
try:
|
||||
dir[olddirloc[1]] = (None, None, None, None,
|
||||
None, None, None, None,
|
||||
newname)
|
||||
finally:
|
||||
dir.close()
|
||||
return
|
||||
|
||||
if is_dir and self.is_ancestor(newparentdirloc, olddirloc):
|
||||
raise io_error, (EINVAL, "cannot move directory"
|
||||
" beneath itself", oldpathname)
|
||||
|
||||
|
||||
newparentdir = None
|
||||
newent = None
|
||||
try:
|
||||
tmpmode = (oldent[0] & ~DF_DIR) | DF_FILE
|
||||
|
||||
(newdirloc, newent) \
|
||||
= self.create_dir_entry(newparentdirloc,
|
||||
newname, tmpmode)
|
||||
|
||||
newent[:8] = oldent[:8]
|
||||
newparentdir = self._opendir_dirloc(newparentdirloc)
|
||||
newparentdir.write_raw_ent(newdirloc[1], newent, True)
|
||||
newent = None
|
||||
|
||||
oldent[0] &= ~DF_EXISTS
|
||||
self.update_dirent_all(olddirloc, None, oldent)
|
||||
|
||||
except:
|
||||
if newent != None:
|
||||
self.delete_dirloc(newdirloc, False,
|
||||
newpathname)
|
||||
finally:
|
||||
if newparentdir != None:
|
||||
newparentdir.close()
|
||||
|
||||
if not is_dir:
|
||||
return
|
||||
|
||||
newdir = self._opendir_dirloc(newdirloc)
|
||||
try:
|
||||
dotent = list(newdir[0])
|
||||
dotent[4:6] = newdirloc
|
||||
newdir.write_raw_ent(0, dotent, False)
|
||||
finally:
|
||||
newdir.close()
|
||||
|
||||
|
||||
def import_save_file(self, sf, ignore_existing, dirname = None):
|
||||
"""Copy the contents a ps2_save_file object to a directory.
|
||||
|
||||
@ -1468,30 +1569,20 @@ class ps2mc(object):
|
||||
|
||||
dir_ent = sf.get_directory()
|
||||
if dirname == None:
|
||||
dir_ent_name = dir_ent[8]
|
||||
dirname = "/" + dir_ent[8]
|
||||
else:
|
||||
if dirname == "":
|
||||
raise path_not_found, dirname
|
||||
|
||||
# remove trailing slashes
|
||||
dirname = dirname.rstrip("/")
|
||||
if dirname == "":
|
||||
dirname = "/"
|
||||
dir_ent_name = dirname.split("/")[0]
|
||||
|
||||
(root_dirloc, ent, is_dir) = self.path_search(dirname)
|
||||
if root_dirloc == None:
|
||||
raise path_not_found, dirname
|
||||
if ent != None:
|
||||
if ent[0] != 0:
|
||||
if ignore_existing:
|
||||
return False
|
||||
raise io_error, (EEXIST, "directory exists", dirname)
|
||||
name = ent[8]
|
||||
mode = DF_DIR | (dir_ent[0] & ~DF_FILE)
|
||||
|
||||
(dir_dirloc, ent) = self.create_dir_entry(root_dirloc,
|
||||
dir_ent_name,
|
||||
mode)
|
||||
name, mode)
|
||||
try:
|
||||
assert dirname != "/"
|
||||
dirname = dirname + "/"
|
||||
@ -1541,7 +1632,9 @@ class ps2mc(object):
|
||||
|
||||
dir = self._opendir_dirloc(root_dirloc, "r+b")
|
||||
try:
|
||||
dir[dir_dirloc[1]] = dir_ent
|
||||
a = dir_ent[:]
|
||||
a[8] = None # don't change the name
|
||||
dir[dir_dirloc[1]] = a
|
||||
finally:
|
||||
dir.close()
|
||||
|
||||
@ -1552,7 +1645,7 @@ class ps2mc(object):
|
||||
(dir_dirloc, dirent, is_dir) = self.path_search(filename)
|
||||
if dir_dirloc == None:
|
||||
raise path_not_found, filename
|
||||
if dirent == None:
|
||||
if dirent[0] == 0:
|
||||
raise dir_not_found, filename
|
||||
if not is_dir:
|
||||
raise io_error, (ENOTDIR, "not a directory", filename)
|
||||
@ -1619,7 +1712,7 @@ class ps2mc(object):
|
||||
(dirloc, ent, is_dir) = self.path_search(dirname)
|
||||
if dirloc == None:
|
||||
raise path_not_found, dirname
|
||||
if ent == None:
|
||||
if ent[0] == 0:
|
||||
raise dir_not_found, dirname
|
||||
if not is_dir:
|
||||
raise io_error, (ENOTDIR, "not a directory", dirname)
|
||||
@ -1740,24 +1833,33 @@ class ps2mc(object):
|
||||
|
||||
return ret
|
||||
|
||||
def _glob(self, dirname, components):
|
||||
def _globdir(self, dirname, components, is_dir):
|
||||
pattern = components[0]
|
||||
if len(components) == 1:
|
||||
if pattern == "":
|
||||
return [dirname]
|
||||
if dirname == "":
|
||||
dir = self.dir_open(".")
|
||||
else:
|
||||
dir = self.dir_open(dirname)
|
||||
try:
|
||||
return [dirname + ent[8]
|
||||
for ent in dir
|
||||
if ((ent[0] & DF_EXISTS)
|
||||
and (ent[8] not in [".", ".."]
|
||||
or ent[8] == pattern)
|
||||
and fnmatch.fnmatchcase(ent[8],
|
||||
pattern))]
|
||||
finally:
|
||||
dir.close()
|
||||
if pattern == "":
|
||||
return self._glob(dirname + "/", components[1:])
|
||||
try:
|
||||
return [dirname + ent[8]
|
||||
for ent in dir
|
||||
if ((ent[0] & DF_EXISTS)
|
||||
and (not is_dir or (ent[8] & DF_DIR))
|
||||
and (ent[8] not in [".", ".."]
|
||||
or ent[8] == pattern)
|
||||
and fnmatch.fnmatchcase(ent[8],
|
||||
pattern))]
|
||||
finally:
|
||||
dir.close()
|
||||
|
||||
def _glob(self, dirname, components, is_dir):
|
||||
pattern = components[0]
|
||||
components = components[1:]
|
||||
|
||||
if len(components) == 1:
|
||||
_glob = self._globdir
|
||||
else:
|
||||
_glob = self._glob
|
||||
|
||||
if dirname == "":
|
||||
dir = self.dir_open(".")
|
||||
else:
|
||||
@ -1774,18 +1876,28 @@ class ps2mc(object):
|
||||
continue
|
||||
elif not fnmatch.fnmatchcase(name, pattern):
|
||||
continue
|
||||
ret += self._glob(dirname + name + "/",
|
||||
components[1:])
|
||||
ret += _glob(dirname + name + "/",
|
||||
components, is_dir)
|
||||
finally:
|
||||
dir.close()
|
||||
return ret
|
||||
|
||||
def glob(self, pattern):
|
||||
if pattern == "":
|
||||
return []
|
||||
ret = self._glob("", pattern.split("/"))
|
||||
return [""]
|
||||
(components, relative, isdir) = pathname_split(pattern)
|
||||
if len(components) == 0:
|
||||
return ["/"]
|
||||
if relative:
|
||||
dirname = ""
|
||||
else:
|
||||
dirname = "/"
|
||||
if len(components) == 1:
|
||||
ret = self._globdir(dirname, components, isdir)
|
||||
else:
|
||||
ret = self._glob(dirname, components, isdir)
|
||||
# print pattern, "->", ret
|
||||
return self._glob("", pattern.split("/"))
|
||||
return ret
|
||||
|
||||
def get_icon_sys(self, dirname):
|
||||
"""Get contents of a directory's icon.sys file, if it exits."""
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
"""Functions for working with PS2 memory card directory entries."""
|
||||
|
||||
_SCCS_ID = "@(#) mysc ps2mc_dir.py 1.4 12/10/04 19:11:08\n"
|
||||
_SCCS_ID = "@(#) mymc ps2mc_dir.py 1.4 12/10/04 19:11:08\n"
|
||||
|
||||
import struct
|
||||
import time
|
||||
|
@ -10,7 +10,7 @@ Routines for calculating the Hamming codes, a simple form of error
|
||||
correcting codes (ECC), as used on PS2 memory cards.
|
||||
"""
|
||||
|
||||
_SCCS_ID = "@(#) mysc ps2mc_ecc.py 1.4 07/12/17 02:34:04\n"
|
||||
_SCCS_ID = "@(#) mymc ps2mc_ecc.py 1.4 07/12/17 02:34:04\n"
|
||||
|
||||
import array
|
||||
|
||||
|
14
ps2save.py
14
ps2save.py
@ -7,7 +7,7 @@
|
||||
# A simple interface for working with various PS2 save file formats.
|
||||
#
|
||||
|
||||
_SCCS_ID = "@(#) mysc ps2save.py 1.7 12/10/04 19:17:16\n"
|
||||
_SCCS_ID = "@(#) mymc ps2save.py 1.8 22/01/15 01:25:25\n"
|
||||
|
||||
import sys
|
||||
import os
|
||||
@ -142,6 +142,8 @@ char_substs = {
|
||||
u'\u254b': u"+",
|
||||
u'\u25a0': u"#",
|
||||
u'\u25a1': u"#",
|
||||
u'\u2605': u"*",
|
||||
u'\u2606': u"*",
|
||||
u'\u3001': u",",
|
||||
u'\u3002': u".",
|
||||
u'\u3003': u'"',
|
||||
@ -279,7 +281,7 @@ class ps2_save_file(object):
|
||||
self.file_data[i] = data
|
||||
|
||||
def get_directory(self):
|
||||
return self.dirent
|
||||
return self.dirent[:]
|
||||
|
||||
def get_file(self, i):
|
||||
if self._defer_load_max:
|
||||
@ -589,10 +591,10 @@ _bad_filename_chars = ("".join(map(chr, range(32)))
|
||||
_bad_filename_repl = "_" * len(_bad_filename_chars)
|
||||
|
||||
if os.name in ["nt", "os2", "ce"]:
|
||||
_bad_filename_chars += '<>:"/\\|'
|
||||
_bad_filename_repl += "()_'___"
|
||||
_bad_filename_chars2 = _bad_filename_chars + "?* "
|
||||
_bad_filename_repl2 = _bad_filename_repl + "___"
|
||||
_bad_filename_chars += '<>:"/\\|?*'
|
||||
_bad_filename_repl += "()_'_____"
|
||||
_bad_filename_chars2 = _bad_filename_chars + " "
|
||||
_bad_filename_repl2 = _bad_filename_repl + "_"
|
||||
else:
|
||||
_bad_filename_chars += "/"
|
||||
_bad_filename_repl += "_"
|
||||
|
2
round.py
2
round.py
@ -7,7 +7,7 @@
|
||||
# Simple rounding functions.
|
||||
#
|
||||
|
||||
_SCCS_ID = "@(#) mysc round.py 1.3 07/04/17 02:10:27\n"
|
||||
_SCCS_ID = "@(#) mymc round.py 1.3 07/04/17 02:10:27\n"
|
||||
|
||||
def div_round_up(a, b):
|
||||
return (a + b - 1) / b
|
||||
|
@ -1,2 +1,2 @@
|
||||
MYMC_VERSION_BUILD = r'''6'''
|
||||
MYMC_VERSION_BUILD = r'''7'''
|
||||
MYMC_VERSION_MAJOR = r'''2'''
|
||||
|
Loading…
Reference in New Issue
Block a user