-
Notifications
You must be signed in to change notification settings - Fork 1
/
BBlock0x.bb.py
executable file
·106 lines (94 loc) · 3 KB
/
BBlock0x.bb.py
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
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env python3
# https://www.python.org/dev/peps/pep-0343/#transition-plan
from __future__ import with_statement
import ctypes
import glob
import os
import subprocess
import sys
try:
# https://docs.python.org/3.0/whatsnew/3.0.html#builtins
from functools import reduce
except ImportError:
pass
def as_uint32(a):
return a & 0xFFFFFFFF
def uint32_addc(a, b):
c = as_uint32(a) + as_uint32(b)
if c > 0xFFFFFFFF:
c += 1
return as_uint32(c)
def uint32_not(a):
return as_uint32(a) ^ 0xFFFFFFFF
TD_SECTOR = 512
BOOTSECTS = 2
class BootBlock(ctypes.BigEndianStructure):
_fields_ = [
('disk_type', ctypes.c_uint32),
('checksum' , ctypes.c_uint32),
('dos_block', ctypes.c_uint32),
('entry' , ctypes.c_uint32 * (((TD_SECTOR * BOOTSECTS) - 12) // 4))]
@classmethod
def from_rawio(cls, f):
b = cls()
if f.readinto(b) != ctypes.sizeof(cls):
raise Exception('failed to read %s structure' % cls.__name__)
return b
def update_checksum(self):
self.checksum = uint32_not(
reduce(uint32_addc, self.entry,
uint32_addc(self.disk_type, self.dos_block)))
return self
assert ctypes.sizeof(BootBlock) == TD_SECTOR * BOOTSECTS
class BBlock0x:
_BASE = 'BBlock0x'
_VASM = os.path.join('vasm', 'vasmm68k_mot')
@classmethod
def basepath(cls):
return cls._BASE.replace('/', os.sep)
@staticmethod
def dosverc(ver):
return chr(ord('0') + ver)
@classmethod
def outpath(cls, ver):
o = cls.basepath()
if ver != 0:
o += '.dos' + cls.dosverc(ver)
return o + '.bb'
@classmethod
def build(cls, ver):
o = cls.outpath(ver);
if not os.path.isfile(o):
if not os.path.isfile(cls._VASM):
for p in glob.glob(cls._VASM + '*'):
if os.access(p, os.X_OK):
cls._VASM = p
break
subprocess.check_call(
[cls._VASM, '-quiet',
'-Fbin', '-pic', '-m68000', '-no-fpu', '-no-opt',
'-DBBLOCK0X_DOSVER=' + cls.dosverc(ver),
'-DBBLOCK0X_NOINFO=1',
'-o', o, cls.basepath() + '.bb.asm'])
with open(o, 'r+b') as f:
b = BootBlock.from_rawio(f)
c = b.checksum
f.seek(0)
f.write(b.update_checksum())
if c != b.checksum:
print('checksum updated: $%08X -> $%08X' % (c, b.checksum))
@classmethod
def clean(cls, ver):
o = cls.outpath(ver);
if os.path.isfile(o):
os.remove(o)
def main(argv):
r = range(0, 7 + 1)
if (len(argv) > 1) and (argv[1] in ('clean', 'rebuild', 'all')):
[BBlock0x.clean(v) for v in r]
if (len(argv) <= 1) or (argv[1] in ('build', 'rebuild')):
BBlock0x.build(0)
if (len(argv) > 1) and (argv[1] in ('all')):
[BBlock0x.build(v) for v in r]
if __name__ == '__main__':
main(sys.argv)