-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSymbols.py
109 lines (81 loc) · 3.36 KB
/
Symbols.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
107
108
109
import re
# TODO - Nested structure to include child labels
class Symbols:
def __init__(self, filepath, mb):
self.filepath = filepath
self.mb = mb
self.index = 0
self.ROM = {}
self.RAM = {}
self.parseSymbols()
def parseSymbols(self):
with open(self.filepath) as f:
lines = f.readlines()
for line in lines:
self.index += 1
# remove ending whitespace and comments
content = re.sub(r'\W*(;.*)?$', '', line)
# Ignore empty lines
if content:
match = re.match(r'([0-9a-fA-F]{1,2}):([0-9a-fA-F]{4}) (.+)', content)
if(not match):
raise Exception(f'Invalid {self.filepath} file syntax at line {self.index}')
# Get the address
memory, address = self.parseAddress(match)
# Get the name
nameStr = match[3]
name, side = self.parseName(nameStr)
# Save data
if name in memory:
data = memory[name]
if side in data:
if data[side] == address:
print(f'{self.filepath} has duplicated name with the same address: {nameStr}')
else:
raise Exception(f'{self.filepath} has duplicated name with different addresess: {nameStr}')
else:
data[side] = address
else:
memory[name] = {
side : address
}
print(f'Successfully Imported {self.filepath}')
def parseAddress(self, match):
bankStr = match[1]
bank = int(bankStr, 16)
addrStr = match[2]
address = int(addrStr, 16)
memory = self.ROM
invalidAddress = False
# Home bank
if bank == 0:
if address > 0x7FFF:
memory = self.RAM
elif address > 0x3FFF:
invalidAddress = True
# Not home bank
elif address > 0x7FFF and address < 0xE000:
memory = self.RAM
# ROM Address
elif address < 0x4000 or address >= 0xE000 or bank >= self.mb.cartridge.external_rom_count:
invalidAddress = True
# Validate RAM Bank
if memory == self.RAM and bank >= self.mb.cartridge.external_ram_count:
invalidAddress = True
if invalidAddress:
raise Exception(f'Invalid {self.filepath} address at line {self.index}: {bankStr}:{addrStr}')
return memory, (bank, address)
def parseName(self, nameStr):
nameMatch = re.match(r'^([a-zA-Z$_][a-zA-Z0-9$_]*(?:\.[a-zA-Z$_][a-zA-Z0-9$_]*)*)(:End)?$', nameStr)
if not nameMatch:
raise Exception(f'Invalid {self.filepath} name at line {self.index}: {nameStr}')
name = nameMatch[1]
side = 'After' if nameMatch[2] else 'Before'
return name, side
def get(self, name, isAfter=False):
if name in self.ROM:
return self.ROM[name]["After" if isAfter else "Before"]
elif name in self.RAM:
return self.RAM[name]["After" if isAfter else "Before"]
else:
return None