Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
compress_sd_image.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 import sys, os
4 
5 
6 def write24bit(fd, val):
7  os.write(fd, bytearray([(val & 0xFF0000) >> 16, (val & 0xFF00) >> 8, val & 0xFF]))
8 
9 
10 def run(argv):
11  if len(argv) != 2:
12  return "usage: infile outfile"
13  fin = os.open(argv[0], os.O_RDONLY)
14  size = os.fstat(fin).st_size
15  if size & 511:
16  os.close(fin)
17  return "Input file size is not multiple of 512 bytes!"
18  if size > 0x80000000:
19  os.close(fin)
20  return "Too large input file, max supported is 2Gbyte in length!"
21  size >>= 9
22  print("Size is " + str(size) + " blocks.")
23  fout = os.open(argv[1], os.O_TRUNC|os.O_WRONLY|os.O_CREAT)
24  os.write(fout, b"XemuBlockCompressedImage000\0")
25  write24bit(fout, 3) # size of header, currently only one 3 bytes length entity, see the next line ...
26  write24bit(fout, size)
27  tabpos = os.lseek(fout, 0, os.SEEK_CUR)
28  print("Pos-table offset = " + str(tabpos))
29  print("Data offset = " + str(size * 3 + tabpos))
30  os.lseek(fout, size * 3 + tabpos, os.SEEK_SET)
31  datpos = 0
32  bmap = [-1] * size
33  sbmap = [-1] * 256
34  print("Reading all the file ...")
35  ncompressed = 0;
36  for blocknum in range(size):
37  block = os.read(fin, 512)
38  if len(block) != 512:
39  raise IOError("We must have 512 bytes to be able to read at all steps!")
40  fillval = block[0]
41  for i in range(1, 512):
42  if block[i] != fillval:
43  fillval = False
44  break
45  if fillval is False:
46  bmap[blocknum] = datpos
47  if os.write(fout, block) != 512:
48  raise IOError("We must have 512 bytes to be able to written at once!")
49  datpos += 1
50  else:
51  if sbmap[fillval] > -1:
52  bmap[blocknum] = sbmap[fillval]
53  else:
54  sbmap[fillval] = datpos | 0x800000
55  bmap[blocknum] = sbmap[fillval]
56  if os.write(fout, block) != 512:
57  raise IOError("We must have 512 bytes to be able to written at once!")
58  datpos += 1
59  ncompressed += 1
60  #print(block)
61  #print(fillval)
62  #print(len(block))
63  os.lseek(fout, tabpos, os.SEEK_SET)
64  for blocknum in range(size):
65  if bmap[blocknum] < 0:
66  raise RuntimeError("block with -1 ...")
67  write24bit(fout, bmap[blocknum])
68  os.close(fout)
69  os.close(fin)
70  print("Compression ratio will be: " + str(100 * (size - ncompressed) / ncompressed) + "%")
71  return None
72 
73 
74 
75 if __name__ == "__main__":
76  r = run(sys.argv[1:])
77  if r:
78  sys.stderr.write("ERROR: " + r + "\n")
79  sys.exit(1)
80  else:
81  sys.exit(0)
compress_sd_image.run
def run(argv)
Definition: compress_sd_image.py:10
compress_sd_image.write24bit
def write24bit(fd, val)
Definition: compress_sd_image.py:6