Ejemplo n.º 1
0
Archivo: aiv.py Proyecto: Yepoleb/aiv
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        self.scene = QtWidgets.QGraphicsScene()
        self.ui.graphicsView.setScene(self.scene)
        
        self.ui.actionQuit.triggered.connect(self.onQuit)
        self.ui.actionOpen.triggered.connect(self.load_rom)
        self.ui.actionSaveImage.triggered.connect(self.save_image)
        
        self.ui.previmgButton.clicked.connect(self.prev_image)
        self.ui.nextimgButton.clicked.connect(self.next_image)
        self.ui.prevpalButton.clicked.connect(self.prev_palette)
        self.ui.nextpalButton.clicked.connect(self.next_palette)
        
        self.ui.widthSpin.valueChanged.connect(self.update_width)
        self.ui.zoomSpin.valueChanged.connect(self.update_zoom)
        self.ui.colorsSelect.currentIndexChanged.connect(self.update_codec)
        self.ui.tilemapCheck.toggled.connect(self.update_tilemap_enabled)
        
        self.ui.imageInput.editingFinished.connect(self.update_image)
        self.ui.paletteInput.editingFinished.connect(self.update_palette)
        self.ui.tilemapInput.editingFinished.connect(self.update_tilemap)
        
        self.rom = None
        self.pointers = []
        self.codec = None
        
        self.img_pointer = 0
        self.palette_pointer = 0
        self.tilemap_pointer = 0
        self.scale = 2
        self.width = 16
        self.tilemap_enabled = False
        self.display_img = None

        self.update_codec()
Ejemplo n.º 2
0
Archivo: aiv.py Proyecto: Yepoleb/aiv
class Window(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        
        self.scene = QtWidgets.QGraphicsScene()
        self.ui.graphicsView.setScene(self.scene)
        
        self.ui.actionQuit.triggered.connect(self.onQuit)
        self.ui.actionOpen.triggered.connect(self.load_rom)
        self.ui.actionSaveImage.triggered.connect(self.save_image)
        
        self.ui.previmgButton.clicked.connect(self.prev_image)
        self.ui.nextimgButton.clicked.connect(self.next_image)
        self.ui.prevpalButton.clicked.connect(self.prev_palette)
        self.ui.nextpalButton.clicked.connect(self.next_palette)
        
        self.ui.widthSpin.valueChanged.connect(self.update_width)
        self.ui.zoomSpin.valueChanged.connect(self.update_zoom)
        self.ui.colorsSelect.currentIndexChanged.connect(self.update_codec)
        self.ui.tilemapCheck.toggled.connect(self.update_tilemap_enabled)
        
        self.ui.imageInput.editingFinished.connect(self.update_image)
        self.ui.paletteInput.editingFinished.connect(self.update_palette)
        self.ui.tilemapInput.editingFinished.connect(self.update_tilemap)
        
        self.rom = None
        self.pointers = []
        self.codec = None
        
        self.img_pointer = 0
        self.palette_pointer = 0
        self.tilemap_pointer = 0
        self.scale = 2
        self.width = 16
        self.tilemap_enabled = False
        self.display_img = None

        self.update_codec()
    
    def load_rom(self):
        filename, filter_ = QtWidgets.QFileDialog.getOpenFileName(self, "Open ROM file",
            QtCore.QDir.homePath(), "GBA ROM (*.gba);;All files (*)")
        print(filename)
        if not filename:
            return
        
        with open(filename, "rb") as rom_file:
            self.rom = rom_file.read()
        all_pointers = decode.find_pointers(self.rom)
        self.pointers = []
        for pointer in all_pointers:
            if decode.check_valid(self.rom, pointer, strict=False):
                self.pointers.append(pointer)
        self.next_image()
        self.next_palette()
        self.show_status("ROM loaded")

    def set_image(self, pointer):
        self.img_pointer = pointer
        self.ui.imageInput.setText("0x{:X}".format(pointer))
        self.decode_image()

    def set_palette(self, pointer):
        self.palette_pointer = pointer
        self.ui.paletteInput.setText("0x{:X}".format(pointer))
        self.decode_image()

    def set_tilemap(self, pointer):
        self.tilemap_pointer = pointer
        self.ui.tilemapInput.setText("0x{:X}".format(pointer))
        self.decode_image()

    def decode_image(self):
        if self.rom is None:
            self.show_status("No ROM loaded")
            return

        print("Decoding", hex(self.img_pointer))
        if self.tilemap_enabled:
            img = decode.decode_tilemap_at(self.rom, self.codec, self.img_pointer,
                self.palette_pointer, self.tilemap_pointer, self.width)
        else:
            img_offset = decode.get_rom_addr(self.img_pointer)
            next_offset = self.next_pointer(self.img_pointer)
            if next_offset is not None:
                img_len = next_offset - img_offset
            else:
                img_len = len(self.rom) - img_offset
            if img_len > 20480:
                img_len = 20480
            
            img = decode.decode_image_at(self.rom, self.codec, self.img_pointer,
                self.palette_pointer, img_len, self.width)
        
        if type(img) == str: # Error
            error = img
            if error == "PALETTE_TOO_SMALL":
                self.show_status("The compressed data at {} is too small for "
                    "a palette".format(hex(self.palette_pointer)))
            elif error == "PALETTE_DECODE_FAILED":
                self.show_status("Failed to decode palette at {}".format(
                    hex(self.palette_pointer)))
            elif error == "IMAGE_DECODE_FAILED":
                self.show_status("Failed to decode image at {}".format(
                    hex(self.img_pointer)))
            elif error == "TILEMAP_DECODE_FAILED":
                self.show_status("Failed to decode tilemap at {}".format(
                    hex(self.tilemap_pointer)))
            else:
                self.show_status("Unknow error {} occured".format(error))
            img = Image.open("error.png")
        elif not all(x > 0 for x in img.size):
            self.show_status("Image has a size of 0")
            img = Image.open("error.png")
        else: # Success!
            orig_size = img.size
            new_size = (img.size[0] * self.scale, img.size[1] * self.scale)
            img = img.resize(new_size)
            self.clear_status()

        self.display_img = img
        img_qt = ImageQt.ImageQt(self.display_img)
        pixmap = QtGui.QPixmap.fromImage(img_qt)
        pixmap_item = QtWidgets.QGraphicsPixmapItem(pixmap)
        self.scene.clear()
        self.scene.addItem(pixmap_item)
        self.scene.update()
        self.scene.setSceneRect(0,0, img.size[0], img.size[1])
    
    def save_image(self):
        filename, filter_ = QtWidgets.QFileDialog.getSaveFileName(self, "Save Image",
            QtCore.QDir.homePath(), "PNG Image (*.png);;All files (*)")
        if not filename:
            return
        
        if not filename.lower().endswith(".png"):
            filename += ".png"
        
        if not self.display_img:
            self.show_status("No Image loaded")
            return
        
        self.display_img.save(filename)
        self.show_status("Saved Image!")
    
    def next_pointer(self, pointer):
        new_index = bisect.bisect_right(self.pointers, pointer)
        if new_index < len(self.pointers):
            return self.pointers[new_index]
        else:
            return None

    def prev_pointer(self, pointer):
        new_index = bisect.bisect_left(self.pointers, pointer) - 1
        if new_index >= 0:
            return self.pointers[new_index]
        else:
            return None

    def next_image(self):
        new_pointer = self.next_pointer(self.img_pointer)
        if new_pointer is not None:
            self.set_image(new_pointer)
    
    def prev_image(self):
        new_pointer = self.prev_pointer(self.img_pointer)
        if new_pointer is not None:
            self.set_image(new_pointer)

    def next_palette(self):
        new_pointer = self.next_pointer(self.palette_pointer)
        if new_pointer is not None:
            self.set_palette(new_pointer)
    
    def prev_palette(self):
        new_pointer = self.prev_pointer(self.palette_pointer)
        if new_pointer is not None:
            self.set_palette(new_pointer)
    
    def update_width(self):
        self.width = self.ui.widthSpin.value()
        self.decode_image()
    
    def update_zoom(self):
        self.scale = self.ui.zoomSpin.value()
        self.decode_image()
    
    def update_codec(self):
        codec_text = self.ui.colorsSelect.currentText()
        if "2bpp" in codec_text:
            self.codec = LinearCodec(2, LinearCodec.REVERSE_ORDER)
        elif "8bpp" in codec_text:
            self.codec = LinearCodec(8, LinearCodec.REVERSE_ORDER)
        else: # 4bpp
            self.codec = LinearCodec(4, LinearCodec.REVERSE_ORDER)
        self.decode_image()

    def parse_int(self, int_str):
        try:
            num = int(int_str, 0)
            return num
        except:
            self.ui.statusbar.showMessage("Could not convert {} to a number"
                .format(int_str))
            return None

    def update_image(self):
        pointer_str = self.ui.imageInput.text()
        pointer = self.parse_int(pointer_str)
        if pointer is None:
            return
        self.set_image(pointer)

    def update_palette(self):
        pointer_str = self.ui.paletteInput.text()
        pointer = self.parse_int(pointer_str)
        if pointer is None:
            return
        self.set_palette(pointer)

    def update_tilemap(self):
        pointer_str = self.ui.tilemapInput.text()
        pointer = self.parse_int(pointer_str)
        if pointer is None:
            return
        self.set_tilemap(pointer)
    
    def update_tilemap_enabled(self):
        self.tilemap_enabled = self.ui.tilemapCheck.isChecked()
        if self.tilemap_enabled:
            self.ui.tilemapLabel.setEnabled(True)
            self.ui.tilemapInput.setEnabled(True)
        else:
            self.ui.tilemapLabel.setEnabled(False)
            self.ui.tilemapInput.setEnabled(False)
        self.decode_image()
    
    def show_status(self, text):
        self.ui.statusbar.showMessage(text)
        print(text)
    
    def clear_status(self):
        self.ui.statusbar.clearMessage()

    def onQuit(self):
        win.close()