def directive_ram(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) size = self.parse_integer(instr.tokens[1], 64, False) if size is None or size < 1: raise InvalidArgumentsForDirective(instr) self.org_counter += size
def directive_org(self, instr): previous_org = self.current_org previous_org_end = self.current_org_end previous_org_counter = self.org_counter if len(instr.tokens) not in (2, 3): raise InvalidArgumentsForDirective() self.current_org = self.parse_integer(instr.tokens[1]) if self.current_org is None: raise InvalidArgumentsForDirective() if len(instr.tokens) == 3: self.current_org_end = self.parse_integer(instr.tokens[2]) if self.current_org_end is None or self.current_org_end < self.current_org: raise InvalidArgumentsForDirective() self.org_counter = 0 # check if need to fill if previous_org_end > 0: # overlap check: if previous_org + previous_org_counter > self.current_org: raise AddressOverlap() # NOTE: we have to NOT set org_counter here! (leave it as 0, as this is a new one .org) # new org is is higher than the previous end if self.current_org > previous_org_end: blob = bytes([self.fill_value] * ((previous_org_end + 1) - (previous_org + previous_org_counter))) self.assembled_bytes += blob # new org is lower than previous end but higher than previous start elif self.current_org <= previous_org_end and self.current_org > previous_org: blob += bytes([self.fill_value] * (self.current_org - (previous_org + previous_org_counter))) self.assembled_bytes += blob else: raise AddressOverlap()
def directive_section(self, instr): if len(instr.tokens) not in (3, 4): raise InvalidArgumentsForDirective(instr) name = self.stringify(instr.tokens[1]) if name in self.sections: raise SectionAlreadyDefined(instr) permissions = instr.tokens[2] if not all( [True if letter in 'RWXE' else False for letter in permissions]): raise InvalidArgumentsForDirective(instr) if len(instr.tokens) == 4: new_org_start = self.parse_integer(instr.tokens[3], 64, False) if new_org_start is None: raise InvalidArgumentsForDirective(instr) self.change_org(new_org_start, 0) if self.current_section: self.sections[self.current_section]['end'] = self.pc self.sections[self.current_section]['size'] = len( self.assembled_bytes) - self.sections[ self.current_section]['offset'] self.current_section = name self.sections[self.current_section] = { 'start': self.pc, 'offset': len(self.assembled_bytes), 'permissions': permissions }
def directive_repeat(self, instr): if self.repeat is not None: raise UnsupportedNestedRepeat(instr) if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) size = self.parse_integer(instr.tokens[1], 64, False) if size is None or size <= 0: raise InvalidArgumentsForDirective(instr) self.repeat = (size, len(self.assembled_bytes))
def directive_align(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) size = self.parse_integer(instr.tokens[1], 64, False) if size is None: raise InvalidArgumentsForDirective(instr) mod = (self.current_org + self.org_counter) % size if mod != 0: blob = bytes([self.fill_value]) * (size - mod) self.append_assembled_bytes(blob)
def _cartridge_fill(self, instr, address, size): if not self.cartridge_set: raise CartidgeHeaderNotSet(instr) if len(instr.tokens) < 2: raise InvalidArgumentsForDirective(instr) try: blob = self.parse_bytes_or_ascii(instr.tokens[1:]) except LabelNotAllowed: raise InvalidArgumentsForDirective(instr) from None if len(blob) > size: raise InvalidArgumentsForDirective(instr) for index, byte in enumerate(blob): self.assembled_bytes[address + index] = byte
def directive_org(self, instr): if len(instr.tokens) not in (2, 3): raise InvalidArgumentsForDirective(instr) new_org_start = self.parse_integer(instr.tokens[1], 64, False) if new_org_start is None: raise InvalidArgumentsForDirective(instr) new_org_end = 0 if len(instr.tokens) == 3: new_org_end = self.parse_integer(instr.tokens[2], 64, False) if new_org_end is None: raise InvalidArgumentsForDirective(instr) self.change_org(new_org_start, new_org_end)
def directive_fill(self, instr): if len(instr.tokens) not in (2, 3): raise InvalidArgumentsForDirective(instr) size = self.parse_integer(instr.tokens[1], 64, False) if size is None: raise InvalidArgumentsForDirective(instr) value = self.fill_value if len(instr.tokens) == 3: value = self.parse_integer(instr.tokens[2], 8, False) if value is None: raise InvalidArgumentsForDirective(instr) blob = bytes([value] * size) self.append_assembled_bytes(blob)
def directive_fill(self, instr): if len(instr.tokens) not in (2, 3): raise InvalidArgumentsForDirective() size = self.parse_integer(instr.tokens[1]) if size is None: raise InvalidArgumentsForDirective() value = self.fill_value if len(instr.tokens) == 3: value = self.parse_integer(instr.tokens[2]) if value is None: raise InvalidArgumentsForDirective() blob = bytes([value] * size) self.assembled_bytes += blob self.org_counter += len(blob)
def directive_upto(self, instr): if len(instr.tokens) not in (2, 3): raise InvalidArgumentsForDirective(instr) offset = self.parse_integer(instr.tokens[1], 64, False) if offset is None: raise InvalidArgumentsForDirective(instr) if offset < len(self.assembled_bytes): raise AddressOverlap(instr) value = self.fill_value if len(instr.tokens) == 3: value = self.parse_integer(instr.tokens[2], 8, False) if value is None: raise InvalidArgumentsForDirective(instr) blob = bytes([value] * (offset - (self.pc - self.current_org))) self.append_assembled_bytes(blob)
def _build_tiles(self, instr): def _convert_cell(image, cell_x, cell_y): planes = [] for y in range(0, 8): byte0 = 0 byte1 = 0 for x in range(0, 8): pixel_x = cell_x * 8 + x pixel_y = cell_y * 8 + y pixel_value = image.getpixel((pixel_x, pixel_y)) if not 0 <= pixel_value <= 3: raise InvalidPaletteEntry(instr) byte0 |= (pixel_value & 0x1) << (7 - x) byte1 |= (pixel_value >> 1) << (7 - x) planes.append((byte0, byte1)) blob = b'' for plane in planes: blob += bytes(plane) return blob if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) filename = self.stringify(instr.tokens[1]) from PIL import Image image = Image.open(filename) if image.mode != 'P': raise OnlyIndexedImagesAreSupported(instr) width, height = image.size if (width % 8) != 0 or (height % 8) != 0: raise InvalidImageSize(instr) for cell_y in range(0, height // 8): for cell_x in range(0, width // 8): blob = _convert_cell(image, cell_x, cell_y) self.append_assembled_bytes(blob)
def directive_export(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) name = self.stringify(instr.tokens[1]) if name in self.exports: raise SymbolAlreadyExported(instr) self.exports.append(name)
def directive_incbin(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) filename = self.stringify(instr.tokens[1]) with open(filename, 'rb') as f: blob = f.read() self.append_assembled_bytes(blob)
def directive_incbin(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective() filename = instr.tokens[1] with open(filename, 'rb') as f: blob = f.read() self.assembled_bytes += blob self.org_counter += len(blob)
def directive_log(self, instr): if len(instr.tokens) > 1: if instr.tokens[1].upper() == 'ON': self.log = True elif instr.tokens[1].upper() == 'OFF': self.log = False else: InvalidArgumentsForDirective() else: self.log = True
def directive_inccsv_le16(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) import csv filename = self.stringify(instr.tokens[1]) blob = b'' with open(filename, 'r') as f: csv_reader = csv.reader(f) for row in csv_reader: for column in row: value = self.parse_integer(column, 16, False) if value is None: raise LabelNotAllowed(instr) blob += pack_le16u(value) self.append_assembled_bytes(blob)
def directive_incjson(self, instr): if len(instr.tokens) != 3: raise InvalidArgumentsForDirective(instr) import json filename = self.stringify(instr.tokens[1]) key = self.stringify(instr.tokens[2]) blob = b'' with open(filename, 'rb') as f: parsed = json.load(f) keys = key.split('.') for key_part in keys: parsed = parsed[key_part] for item in parsed: if not isinstance(item, int): item = self.parse_integer(item, 8, False) if item is None: raise LabelNotAllowed(instr) blob += bytes((item, )) self.append_assembled_bytes(blob)
def _build_chr_pattern_table(self, instr): def _convert_cell(image, cell_x, cell_y): plane0 = [] plane1 = [] for y in range(0, 8): byte0 = 0 byte1 = 0 for x in range(0, 8): pixel_x = cell_x * 8 + x pixel_y = cell_y * 8 + y pixel_value = image.getpixel((pixel_x, pixel_y)) if not 0 <= pixel_value <= 3: raise InvalidPaletteEntry(instr) byte0 |= (pixel_value & 0x1) << (7 - x) byte1 |= (pixel_value >> 1) << (7 - x) plane0.append(byte0) plane1.append(byte1) blob = b'' for byte in plane0: blob += bytes((byte,)) for byte in plane1: blob += bytes((byte,)) return blob if len(instr.tokens) != 2: raise InvalidArgumentsForDirective(instr) filename = self.stringify(instr.tokens[1]) from PIL import Image image = Image.open(filename) if image.mode != 'P': raise OnlyIndexedImagesAreSupported(instr) width, height = image.size if width != 128 or height != 128: raise InvalidImageSize(instr) for cell_y in range(0, 16): for cell_x in range(0, 16): blob = _convert_cell(image, cell_x, cell_y) self.append_assembled_bytes(blob)
def directive_include(self, instr): if len(instr.tokens) != 2: raise InvalidArgumentsForDirective() filename = instr.tokens[1] with open(filename) as f: self.assemble(f.read(), context=filename)
def directive_define(self, instr): if len(instr.tokens) != 3: raise InvalidArgumentsForDirective() self.defines[instr.tokens[1]] = instr.tokens[2]