Repository: Baekalfen/PyBoy
File: pyboy/core/cartridge/base_mbc.py (Python)

Code before:

        for bank in range(self.external_ram_count):
            for byte in range(8*1024):
                f.write(self.rambanks[bank][byte])

        logger.debug("RAM saved.")

    def load_ram(self, f):
        if not self.rambank_initialized:
            logger.warning("Loading RAM is not supported on {}".format(self.carttype))
            return

        for bank in range(self.external_ram_count):
            for byte in range(8*1024):
                self.rambanks[bank][byte] = f.read()

        logger.debug("RAM loaded.")

    def init_rambanks(self, n):
        if n is None:
            return

        self.rambank_initialized = True

        # In real life the values in RAM are scrambled on initialization.
        self.rambanks = [array.array('B', [0] * (8*1024)) for _ in range(n)]

    def getgamename(self, rombanks):
        return "".join([chr(x) for x in rombanks[0][0x0134:0x0142]]).rstrip("\0")

    def setitem(self, address, value):
        raise Exception("Cannot set item in MBC")

    def getitem(self, address):
        if 0x0000 <= address < 0x4000:
            return self.rombanks[0][address]
        elif 0x4000 <= address < 0x8000:
            return self.rombanks[self.rombank_selected % len(self.rombanks)][address-0x4000]
        elif 0xA000 <= address < 0xC000:
            if not self.rambank_initialized:
                raise logger.error("RAM banks not initialized: %s" % hex(address))

            if not self.rambank_enabled:
                return 0xFF

            if self.rtc_enabled and 0x08 <= self.rambank_selected <= 0x0C:
                return self.rtc.getregister(self.rambank_selected)
            else:
                return self.rambanks[self.rambank_selected % len(self.rombanks)][address-0xA000]
        else:
            raise logger.error("Reading address invalid: %s" % address)

Review comment (suggestion):
For the time being, this still needs to be there. It's making the memory allocation easier on Cython. If you want to fix it in another PR, I've found a way to use malloc in my plugin branch.

Code after:
        for bank in range(self.external_ram_count):
            for byte in range(8*1024):
                f.write(self.rambanks[bank][byte])

        logger.debug("RAM saved.")

    def load_ram(self, f):
        if not self.rambank_initialized:
            logger.warning("Loading RAM is not supported on {}".format(self.carttype))
            return

        for bank in range(self.external_ram_count):
            for byte in range(8*1024):
                self.rambanks[bank][byte] = f.read()

        logger.debug("RAM loaded.")

    def init_rambanks(self, n):
        if n is None:
            return

        self.rambank_initialized = True

        # In real life the values in RAM are scrambled on initialization.
        # Allocating the maximum, as it is easier in Cython. And it's just 128KB...
        self.rambanks = [array.array('B', [0] * (8*1024)) for _ in range(16)]

    def getgamename(self, rombanks):
        return "".join([chr(x) for x in rombanks[0][0x0134:0x0142]]).rstrip("\0")

    def setitem(self, address, value):
        raise Exception("Cannot set item in MBC")

    def getitem(self, address):
        if 0x0000 <= address < 0x4000:
            return self.rombanks[0][address]
        elif 0x4000 <= address < 0x8000:
            return self.rombanks[self.rombank_selected % len(self.rombanks)][address-0x4000]
        elif 0xA000 <= address < 0xC000:
            if not self.rambank_initialized:
                logger.error("RAM banks not initialized: %s" % hex(address))

            if not self.rambank_enabled:
                return 0xFF

            if self.rtc_enabled and 0x08 <= self.rambank_selected <= 0x0C:
                return self.rtc.getregister(self.rambank_selected)
            else:
                return self.rambanks[self.rambank_selected % self.external_ram_count][address-0xA000]
        else:
            logger.error("Reading address invalid: %s" % address)