Mercurial > hg > tilerswift
changeset 101:822e2fb5197c
refactor: move the NES ROM manipulation code into its own module
Also, rename the color module to colour 'cause I got tired of
misspelling it when I didn't have to.
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Sat, 14 Sep 2019 23:33:01 -0400 |
parents | c575bdd3d087 |
children | 53af53d6c81e |
files | colors.py colours.py nes.py tilerswift |
diffstat | 3 files changed, 96 insertions(+), 91 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/nes.py @@ -0,0 +1,94 @@ +from PyQt5 import QtGui as QG + +from colours import TILE_PALETTES, palette_to_qt + + +class NES_ROM(object): + def __init__(self, filename): + self.filename = filename + self.read_rom() + + def read_rom(self): + with open(self.filename, 'rb') as f: + self.ines = f.read() + + self.header = self.ines[0:16] + body = self.ines[16:] + PRG_size = self.header[4]*16384 + CHR_size = self.header[5]*8192 + + self.PRG = body[0:PRG_size] + if CHR_size == 0: + # No chr, just read the whole ROM as tiles + tile_data = body + self.CHR = None + else: + self.CHR = body[PRG_size:PRG_size+CHR_size] + tile_data = self.CHR + + self.tiles = [Tile(tile_data[i:i+16]) for i in range(0, len(tile_data), 16)] + + +class Tile(object): + + default_palette = TILE_PALETTES["Primary"] + + def __init__(self, raw_tile): + super().__init__() + + self.raw_tile = raw_tile + self.set_palette(self.default_palette.copy()) + + def __repr__(self): + num_to_ascii = {0: " ", 1: ".", 2: "o", 3: "#"} + return "_"*10 + "\n" + "\n".join( + "[" + "".join([num_to_ascii[val] for val in row]) + "]" + for row in self.tile + ) + "\n" + "-"*10 + + def set_palette(self, new_palette): + self.palette = new_palette.copy() + self.update_pixmap() + + def update_pixmap(self): + img_data = bytes(sum(self.tile, [])) + image = QG.QImage(img_data, 8, 8, QG.QImage.Format_Indexed8) + image.setColorTable(palette_to_qt(self.palette)) + self.pixmap = QG.QPixmap(image) + + def get_tile(self): + if getattr(self, "_tile", None) is None: + self._tile = self.parse_tile(self.raw_tile) + return self._tile + + def set_tile(self, tile): + del self._tile + self.raw_tile = self.unparse_tile(tile) + + self.update_pixmap() + + def del_tile(self): + del self._tile + del self.raw_tile + + tile = property(get_tile, set_tile, del_tile, "A tile parsed as an 8x8 array of ints") + + @classmethod + def parse_tile(cls, tile): + """Given a raw tile's bytes, convert it to an 8x8 array of integers.""" + lowplane, hiplane = tile[0:8], tile[8:16] + rows = [] + for lowbyte, hibyte in zip(lowplane, hiplane): + row = [ + ((lowbyte >> idx) & 1) + 2*((hibyte >> idx) & 1) + for idx in range(7, -1, -1) + ] + rows.append(row) + return rows + + @classmethod + def unparse_tile(cls, rows): + """Given an 8x8 array of integers, convert it to a raw tile's bytes.""" + lowplane = bytes([int(''.join(str(num & 1) for num in row), 2) for row in rows]) + hiplane = bytes([int(''.join(str((num & 2) >> 1) for num in row), 2) for row in rows]) + return lowplane + hiplane
--- a/tilerswift +++ b/tilerswift @@ -3,101 +3,12 @@ from PyQt5 import QtCore as QC, QtGui as QG, QtWidgets as QW -from colors import ( +from colours import ( NES_PALETTE, TILE_PALETTES, is_dark, palette_to_qt, widget_icon_path ) - -class NES_ROM(object): - def __init__(self, filename): - self.filename = filename - self.read_rom() - - def read_rom(self): - with open(self.filename, 'rb') as f: - self.ines = f.read() - - self.header = self.ines[0:16] - body = self.ines[16:] - PRG_size = self.header[4]*16384 - CHR_size = self.header[5]*8192 - - self.PRG = body[0:PRG_size] - if CHR_size == 0: - # No chr, just read the whole ROM as tiles - tile_data = body - self.CHR = None - else: - self.CHR = body[PRG_size:PRG_size+CHR_size] - tile_data = self.CHR - - self.tiles = [Tile(tile_data[i:i+16]) for i in range(0, len(tile_data), 16)] - - -class Tile(object): - - default_palette = TILE_PALETTES["Primary"] - - def __init__(self, raw_tile): - super().__init__() - - self.raw_tile = raw_tile - self.set_palette(self.default_palette.copy()) - - def __repr__(self): - num_to_ascii = {0: " ", 1: ".", 2: "o", 3: "#"} - return "_"*10 + "\n" + "\n".join( - "[" + "".join([num_to_ascii[val] for val in row]) + "]" - for row in self.tile - ) + "\n" + "-"*10 - - def set_palette(self, new_palette): - self.palette = new_palette.copy() - self.update_pixmap() - - def update_pixmap(self): - img_data = bytes(sum(self.tile, [])) - image = QG.QImage(img_data, 8, 8, QG.QImage.Format_Indexed8) - image.setColorTable(palette_to_qt(self.palette)) - self.pixmap = QG.QPixmap(image) - - def get_tile(self): - if getattr(self, "_tile", None) is None: - self._tile = self.parse_tile(self.raw_tile) - return self._tile - - def set_tile(self, tile): - del self._tile - self.raw_tile = self.unparse_tile(tile) - - self.update_pixmap() - - def del_tile(self): - del self._tile - del self.raw_tile - - tile = property(get_tile, set_tile, del_tile, "A tile parsed as an 8x8 array of ints") - - @classmethod - def parse_tile(cls, tile): - """Given a raw tile's bytes, convert it to an 8x8 array of integers.""" - lowplane, hiplane = tile[0:8], tile[8:16] - rows = [] - for lowbyte, hibyte in zip(lowplane, hiplane): - row = [ - ((lowbyte >> idx) & 1) + 2*((hibyte >> idx) & 1) - for idx in range(7, -1, -1) - ] - rows.append(row) - return rows - - @classmethod - def unparse_tile(cls, rows): - """Given an 8x8 array of integers, convert it to a raw tile's bytes.""" - lowplane = bytes([int(''.join(str(num & 1) for num in row), 2) for row in rows]) - hiplane = bytes([int(''.join(str((num & 2) >> 1) for num in row), 2) for row in rows]) - return lowplane + hiplane +from nes import NES_ROM, Tile class GridHolder(object):