Ticket #3657: ut64

File ut64, 7.6 KB (added by Nicolas Rybkin, 5 years ago)
Line 
1#! /usr/bin/env python
2#Written by Nicolas Rybkin
3#18.07.2015
4import sys, os, time
5
6CHAR_MAP = {32: ' ', 33: '!', 34: '"', 35: '#', 37: '%', 38: '&', 39: "'",
7            40: '(', 41: ')', 42: '*', 43: '+', 44: ',', 45: '-', 46: '.',
8            47: '_', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5',
9            54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 60: '<', 61: '=',
10            62: '>', 63: '?', 64: '@', 65: 'a', 66: 'b', 67: 'c', 68: 'd',
11            69: 'e', 70: 'f', 71: 'g', 72: 'h', 73: 'i', 74: 'j', 75: 'k',
12            76: 'l', 77: 'm', 78: 'n', 79: 'o', 80: 'p', 81: 'q', 82: 'r',
13            83: 's', 84: 't', 85: 'u', 86: 'v', 87: 'w', 88: 'x', 89: 'y',
14            90: 'z', 91: '[', 93: ']', 94: '^', 95: '_', 96: '`',
15            97: 'A', 98: 'B', 99: 'C',
16            100: 'D', 101: 'E', 102: 'F', 103: 'G', 104: 'H', 105: 'I',
17            106: 'J', 107: 'K', 108: 'L', 109: 'M', 110: 'N', 111: 'O',
18            112: 'P', 113: 'Q', 114: 'R', 115: 'S', 116: 'T', 117: 'U',
19            118: 'V', 119: 'W', 120: 'X', 121: 'Y', 122: 'Z', 193: 'A',
20            194: 'B', 195: 'C', 196: 'D', 197: 'E', 198: 'F', 199: 'G',
21            200: 'H', 201: 'I', 202: 'J', 203: 'K', 204: 'L', 205: 'M',
22            206: 'N', 207: 'O', 208: 'P', 209: 'Q', 210: 'R', 211: 'S',
23            212: 'T', 213: 'U', 214: 'V', 215: 'W', 216: 'X', 217: 'Y',
24            218: 'Z'}
25
26FILE_TYPES = {0x80 : 'del',
27              0x81 : 'seq',
28              0x82 : 'prg',
29              0x83 : 'usr',
30              0x84 : 'rel',
31              'del': 0x80,
32              'seq': 0x81,
33              'prg': 0x82,
34              'usr': 0x83,
35              'rel': 0x84}
36
37def NameFilter(in_string):
38    out_string = ""
39    for i in xrange(len(in_string)):
40        try:
41            out_string += CHAR_MAP[ord(in_string[i])]
42        except KeyError:
43            out_string += "_"
44    return out_string
45
46tape_file = open(sys.argv[2], "r+b")
47tape_buffer = tape_file.read()
48if tape_buffer[:3] <> "C64":
49    sys.exit('Signature "C64" in the beginning of the file not found.')
50total_entries = ord(tape_buffer[0x22])+(ord(tape_buffer[0x23])<<8)
51used_entries = ord(tape_buffer[0x24])+(ord(tape_buffer[0x25])<<8)
52command = sys.argv[1].upper()
53if command == "LIST":
54    if not used_entries: exit()
55    imgtime = time.strftime("%m/%d/%Y %H:%M:%S",\
56            time.localtime(os.stat(sys.argv[2]).st_mtime))
57    for ptr in xrange(0x40,0x40+(used_entries<<5),32):
58        if ord(tape_buffer[ptr]) == 1:
59            print "-rw-r--r-- 1", 2*"1001", \
60                ord(tape_buffer[ptr+4])+(ord(tape_buffer[ptr+5])<<8)-\
61                ord(tape_buffer[ptr+2])+(ord(tape_buffer[ptr+3])<<8),\
62                imgtime,\
63                NameFilter(tape_buffer[ptr+16:ptr+32]).strip() + "."+\
64                FILE_TYPES[ord(tape_buffer[ptr+1])]
65elif command == "COPYOUT":
66    i = sys.argv[3].rfind(".")
67    if i == -1: sys.exit("Can't COPYOUT file. No type specified.")
68    file_type = FILE_TYPES[sys.argv[3][i+1:]]
69    file_name = sys.argv[3][:i].ljust(16," ")
70    file_found = False
71    for ptr in xrange(0x40,0x40+(used_entries<<5),32):
72        if tape_buffer[ptr] == "\x01" and\
73                NameFilter(tape_buffer[ptr+16:ptr+32]) == file_name and\
74                ord(tape_buffer[ptr+1]) == file_type:
75            file_found = True
76            break
77    if not file_found: sys.exit("File not found")
78    dest_file = open(sys.argv[4],"w")
79    source_buffer = tape_buffer[ptr+2] + tape_buffer[ptr+3]#start address
80    data_offset  =  ord(tape_buffer[ptr+8])       +\
81                    (ord(tape_buffer[ptr+9]) <<8) +\
82                    (ord(tape_buffer[ptr+10])<<16)+\
83                    (ord(tape_buffer[ptr+11])<<24)
84    data_len = ord(tape_buffer[ptr+4])+(ord(tape_buffer[ptr+5])<<8)-\
85                ord(tape_buffer[ptr+2])+(ord(tape_buffer[ptr+3])<<8)
86    source_buffer += tape_buffer[data_offset:data_offset+data_len]
87    dest_file.write(source_buffer)
88    dest_file.close()
89elif command == "COPYIN":
90    src_file = open(sys.argv[4],"r")
91    src_buffer = src_file.read()
92    src_file.close()
93    start_address = ord(src_buffer[0])+(ord(src_buffer[1])<<8)
94    src_buffer = src_buffer[2:]
95    end_address = start_address + len(src_buffer)
96    if used_entries == total_entries:
97        #expand
98        total_entries += 1
99        tape_buffer_ = tape_buffer[:0x22] +\
100            chr(total_entries&0xFF)+chr(total_entries>>8)+\
101            tape_buffer[0x24:0x40]
102        for ptr in xrange(0x40,0x40+(used_entries<<5),32):
103            tape_buffer_ += tape_buffer[ptr:ptr+8]
104            data_offset  =  ord(tape_buffer[ptr+8])       +\
105                            (ord(tape_buffer[ptr+9]) <<8) +\
106                            (ord(tape_buffer[ptr+10])<<16)+\
107                            (ord(tape_buffer[ptr+11])<<24)
108            data_offset += 32
109            for i in xrange(4):
110                tape_buffer_ += chr(data_offset&0xFF)
111                data_offset >>= 8
112            tape_buffer_ += tape_buffer[ptr+12:ptr+32]
113        tape_buffer_ += 32*"\x00"
114        tape_buffer_ += tape_buffer[ptr+32:]
115        tape_buffer = tape_buffer_
116    ptr = 0x40+32*used_entries
117    data_ptr = len(tape_buffer)
118    i = sys.argv[3].rfind(".")
119    if i == -1: sys.exit("Can't COPYIN file. No type specified.")
120    file_type = FILE_TYPES[sys.argv[3][i+1:]]
121    file_name = NameFilter(sys.argv[3][:i]).ljust(16," ")
122    used_entries += 1
123    tape_buffer_ = tape_buffer[:0x22]+\
124                    chr(total_entries&0xFF)+chr(total_entries>>8)+\
125                    chr(used_entries&0xFF)+chr(used_entries>>8)+\
126                    tape_buffer[0x26:ptr]+\
127                    "\x01"+chr(file_type)+\
128                    chr(start_address&0xFF)+\
129                    chr(start_address>>8)+\
130                    chr(end_address&0xFF)+\
131                    chr(end_address>>8)+\
132                    "\x00\x00"
133    for i in xrange(4):
134        tape_buffer_ += chr(data_ptr&0xFF)
135        data_ptr >>= 8
136    tape_buffer_ += 4*"\x00" + file_name
137    data_offset  =  ord(tape_buffer[0x48])      +\
138                    (ord(tape_buffer[0x49])<<8) +\
139                    (ord(tape_buffer[0x4a])<<16)+\
140                    (ord(tape_buffer[0x4b])<<24)
141
142
143    tape_buffer_ += tape_buffer[data_offset:] + src_buffer
144    tape_file.seek(0)
145    tape_file.write(tape_buffer_)
146elif command == "RM":
147    i = sys.argv[3].rfind(".")
148    if i == -1: sys.exit("Can't COPYOUT file. No type specified.")
149    file_type = FILE_TYPES[sys.argv[3][i+1:]]
150    file_name = NameFilter(sys.argv[3][:i]).ljust(16," ")
151    file_found = False
152    for ptr in xrange(0x40,0x40+(used_entries<<5),32):
153        if tape_buffer[ptr+16:ptr+32] == file_name and\
154                ord(tape_buffer[ptr+1]) == file_type:
155            file_found = True
156            break
157    if not file_found: sys.exit("File not found")
158    data_offset  =  ord(tape_buffer[0x48])      +\
159                    (ord(tape_buffer[0x49])<<8) +\
160                    (ord(tape_buffer[0x4a])<<16)+\
161                    (ord(tape_buffer[0x4b])<<24)
162    file_offset  =  ord(tape_buffer[ptr+8])       +\
163                    (ord(tape_buffer[ptr+9])<<8)  +\
164                    (ord(tape_buffer[ptr+10])<<16)+\
165                    (ord(tape_buffer[ptr+11])<<24)
166       
167    used_entries -= 1
168    ptr_ = ptr
169    if used_entries:
170        next_file_offset=ord(tape_buffer[ptr+40])     +\
171                        (ord(tape_buffer[ptr+41])<<8) +\
172                        (ord(tape_buffer[ptr+42])<<16)+\
173                        (ord(tape_buffer[ptr+43])<<24)
174       
175        free_mem = next_file_offset - file_offset
176        tape_buffer_ = tape_buffer[:ptr+32]
177        for ptr in xrange(ptr+32,0x40+((used_entries+1)<<5),32):
178            tape_buffer_ += tape_buffer[ptr:ptr+8]
179            offset = ord(tape_buffer[ptr+8])      +\
180                    (ord(tape_buffer[ptr+9])<<8)  +\
181                    (ord(tape_buffer[ptr+10])<<16)+\
182                    (ord(tape_buffer[ptr+11])<<24)
183            offset -= free_mem
184            for i in xrange(4):
185                tape_buffer_ += chr(offset&0xFF)
186                offset >>= 8
187            tape_buffer_ += tape_buffer[ptr+12:ptr+32]
188        tape_buffer = tape_buffer_ + tape_buffer[ptr+32:]
189    else:
190        next_file_offset = len(tape_buffer)
191    tape_buffer =   tape_buffer[:0x24]+\
192                    chr(used_entries&0xFF)+chr(used_entries>>8)+\
193                    tape_buffer[0x26:ptr_]+\
194                    tape_buffer[ptr_+32:data_offset]+\
195                    32*"\x00"+\
196                    tape_buffer[data_offset:file_offset]+\
197                    tape_buffer[next_file_offset:]
198
199    tape_file.seek(0)
200    tape_file.truncate(len(tape_buffer))
201    tape_file.write(tape_buffer)
202
203elif command == "RMDIR" or command == "MKDIR":
204    sys.exit("Command "+command+" not supported.")
205
206tape_file.close()