Пример #1
0
    def get_pattern_table(self, i, palette):
        for nTileY in range(16):
            for nTileX in range(16):
                nOffset = to_16_bits(nTileY * 256 + nTileX * 16)

                for row in range(8):
                    tile_lsb = to_8_bits(self.ppu_read(i * 0x1000 + nOffset + row + 0x0000))
                    tile_msb = to_8_bits(self.ppu_read(i * 0x1000 + nOffset + row + 0x0008))

                    for col in range(8):
                        pixel = to_8_bits((tile_lsb & 0x01) + (tile_msb & 0x01))

                        tile_lsb >>= 1
                        tile_msb >>= 1

                        self.spr_pattern_tbl[i].set_pixel(
                            nTileX * 8 + (7 - col),
                            nTileY * 8 + row,
                            self.get_colour_from_palette_ram(palette, pixel)
                        )

        return self.spr_pattern_tbl[i]
Пример #2
0
    def cpu_read(self, addr, is_read_only = False):
        if addr > 0xFFFF: print("maior que 16 bits") 
        

        data = 0x00

        
        if is_read_only:
            if   addr == 0x0000: data = self.control.reg
            elif addr == 0x0001: data = self.mask.reg
            elif addr == 0x0002: data = self.status.reg
            elif addr == 0x0003: pass
            elif addr == 0x0004: pass
            elif addr == 0x0005: pass
            elif addr == 0x0006: pass
            elif addr == 0x0007: pass

        else:        
            if   addr == 0x0000: pass
            elif addr == 0x0001: pass
            elif addr == 0x0002:
                #self.status.set_vertical_blank(1)

                data = (self.status.reg & 0xE0) | (self.ppu_data_buffer & 0x1F)

                self.status.set_vertical_blank(0)

                self.address_latch = 0
            elif addr == 0x0003: pass
            elif addr == 0x0004: pass
            elif addr == 0x0005: pass
            elif addr == 0x0006: pass
            elif addr == 0x0007:
                data = self.ppu_data_buffer

                self.ppu_data_buffer = self.ppu_read(self.vram_addr.reg)

                if (self.vram_addr.reg >= 0x3F00): data = self.ppu_data_buffer

                self.vram_addr.reg = to_16_bits(
                    self.vram_addr.reg + (32 if self.control.get_increment_mode() else 1))

        if data > 0xFF: print("maior que 8 bits") 

        return to_8_bits(data)
Пример #3
0
    def ppu_read(self, addr, is_read_only = False):
        if addr > 0xFFFF: print("maior que 16 bits") 

        data = 0x00
        addr &= 0x3FFF

        ret = self.cartridge.ppuRead(addr, data)

        if not(ret == None): data = to_8_bits(ret)

        elif (addr >= 0x0000 and addr <= 0x1FFF):
            data = self.tbl_pattern[(addr & 0x1000) >> 12][addr & 0x0FFF]

        elif (addr >= 0x2000 and addr <= 0x3EFF):
            addr &= 0x0FFF

            if self.cartridge.mirror == c.MIRROR.VERTICAL:
                if (addr >= 0x0000 and addr <= 0x03FF): data = self.tbl_name[0][addr & 0x03FF]
                if (addr >= 0x0400 and addr <= 0x07FF): data = self.tbl_name[1][addr & 0x03FF]
                if (addr >= 0x0800 and addr <= 0x0BFF): data = self.tbl_name[0][addr & 0x03FF]
                if (addr >= 0x0C00 and addr <= 0x0FFF): data = self.tbl_name[1][addr & 0x03FF]

            elif self.cartridge.mirror == c.MIRROR.HORIZONTAL:
                if (addr >= 0x0000 and addr <= 0x03FF): data = self.tbl_name[0][addr & 0x03FF]
                if (addr >= 0x0400 and addr <= 0x07FF): data = self.tbl_name[0][addr & 0x03FF]
                if (addr >= 0x0800 and addr <= 0x0BFF): data = self.tbl_name[1][addr & 0x03FF]
                if (addr >= 0x0C00 and addr <= 0x0FFF): data = self.tbl_name[1][addr & 0x03FF]

        elif (addr >= 0x3F00 and addr <= 0x3FFF):
            addr &= 0x001F

            if (addr == 0x0010): addr = 0x0000
            if (addr == 0x0014): addr = 0x0004
            if (addr == 0x0018): addr = 0x0008
            if (addr == 0x001C): addr = 0x000C

            #data = self.tbl_palette[addr]
            data = self.tbl_palette[addr] & (0x30 if self.mask.get_grayscale() else 0x3F)

        if data > 0xFF: print("maior que 8 bits") 

        return data
Пример #4
0
    def ppu_write(self, addr, data):
        if addr > 0xFFFF: print("maior que 16 bits") 
        if data > 0xFF: print("maior que 8 bits") 

        data = to_8_bits(data)
        addr &= 0x3FFF

        if self.cartridge.ppuWrite(addr, data):
            pass

        elif (addr >= 0x0000 and addr <= 0x1FFF):
            self.tbl_pattern[(addr & 0x1000) >> 12][addr & 0x0FFF] = data

        elif (addr >= 0x2000 and addr <= 0x3EFF):
            addr &= 0x0FFF

            if self.cartridge.mirror == c.MIRROR.VERTICAL:
                if (addr >= 0x0000 and addr <= 0x03FF): self.tbl_name[0][addr & 0x03FF] = data
                if (addr >= 0x0400 and addr <= 0x07FF): self.tbl_name[1][addr & 0x03FF] = data
                if (addr >= 0x0800 and addr <= 0x0BFF): self.tbl_name[0][addr & 0x03FF] = data
                if (addr >= 0x0C00 and addr <= 0x0FFF): self.tbl_name[1][addr & 0x03FF] = data

            elif self.cartridge.mirror == c.MIRROR.HORIZONTAL:
                if (addr >= 0x0000 and addr <= 0x03FF): self.tbl_name[0][addr & 0x03FF] = data
                if (addr >= 0x0400 and addr <= 0x07FF): self.tbl_name[0][addr & 0x03FF] = data
                if (addr >= 0x0800 and addr <= 0x0BFF): self.tbl_name[1][addr & 0x03FF] = data
                if (addr >= 0x0C00 and addr <= 0x0FFF): self.tbl_name[1][addr & 0x03FF] = data

        elif (addr >= 0x3F00 and addr <= 0x3FFF):
            addr &= 0x001F

            if (addr == 0x0010): addr = 0x0000
            if (addr == 0x0014): addr = 0x0004
            if (addr == 0x0018): addr = 0x0008
            if (addr == 0x001C): addr = 0x000C

            self.tbl_palette[addr] = data
Пример #5
0
    def clock(self):        
        if self.scanline >= -1 and self.scanline < 240:
            if self.scanline == 0  and self.cycle == 0: self.cycle = 1
        
            if self.scanline == -1 and self.cycle == 1: self.status.set_vertical_blank(0)
        
            if (self.cycle >= 2 and self.cycle < 258) or (self.cycle >= 321 and self.cycle < 338):
                self._update_shifters()

                value = (self.cycle - 1) % 8

                if value == 0:
                    self._load_background_shifters()
                    self.bg_next_tile_id = self.ppu_read(0x2000 | (self.vram_addr.reg & 0x0FFF))

                    #print(hex(self.bg_next_tile_id))

                elif value == 2:
                    self.bg_next_tile_attrib = self.ppu_read(
                        0x23C0 
                        | (self.vram_addr.get_nametable_y() << 11) 
                        | (self.vram_addr.get_nametable_x() << 10)
                        | ((self.vram_addr.get_coarse_y() >> 2) << 3) 
                        | (self.vram_addr.get_coarse_x() >> 2)
                    )

                    if (self.vram_addr.get_coarse_y() & 0x02): self.bg_next_tile_attrib >>= 4
                    if (self.vram_addr.get_coarse_x() & 0x02): self.bg_next_tile_attrib >>= 2

                    self.bg_next_tile_attrib &= 0x03

                elif value == 4:
                    self.bg_next_tile_lsb = self.ppu_read(
                        (self.control.get_pattern_background() << 12)
                      + (to_16_bits(self.bg_next_tile_id) << 4) + (self.vram_addr.get_fine_y()) + 0
                    )

                    #print("LSB: ", self.bg_next_tile_lsb)

                elif value == 6:
                    self.bg_next_tile_msb = self.ppu_read(
                        (self.control.get_pattern_background() << 12)
                      + (to_16_bits(self.bg_next_tile_id) << 4) + (self.vram_addr.get_fine_y()) + 8
                    )

                    #print("MSB: ", self.bg_next_tile_msb)

                elif value == 7: self._increment_scroll_x()

            if (self.cycle == 256): self._increment_scroll_y()

            if (self.cycle == 257):
                self._load_background_shifters()
                self._transfer_address_x()

            if (self.cycle == 338 or self.cycle == 340):
                self.bg_next_tile_id = self.ppu_read(0x2000 | (self.vram_addr.reg & 0x0FFF))

            if (self.scanline == -1 and self.cycle >= 280 and self.cycle < 305):
                self._transfer_address_y()
            
        if (self.scanline == 240): pass # Post Render Scanline - Do Nothing!
        
        if self.scanline >= 241 and self.scanline < 261:        
            if self.scanline == 241 and self.cycle == 1:
                #print("set_vertical_blank 1")
                self.status.set_vertical_blank(1)

                if self.control.get_enable_nmi(): self.nmi = True
        
        bg_pixel = 0x00
        bg_palette = 0x00

        if self.mask.get_render_background():
            bit_mux = to_16_bits(0x8000 >> self.fine_x)

            p0_pixel = to_8_bits((self.bg_shifter_pattern_lo & bit_mux) > 0)
            p1_pixel = to_8_bits((self.bg_shifter_pattern_hi & bit_mux) > 0)

            bg_pixel = to_8_bits((p1_pixel << 1) | p0_pixel)

            bg_pal0 = to_8_bits((self.bg_shifter_attrib_lo & bit_mux) > 0)
            bg_pal1 = to_8_bits((self.bg_shifter_attrib_hi & bit_mux) > 0)
            bg_palette = to_8_bits((bg_pal1 << 1) | bg_pal0)

        self.spr_screen.set_pixel(
            self.cycle - 1, self.scanline, self.get_colour_from_palette_ram(bg_palette, bg_pixel))

        #fake = 0x30
        #if int((n.random.rand() * 15)) % 2: fake = 0x3F
        #self.spr_screen.set_pixel( self.cycle - 1, self.scanline, self.pal_screen[fake])

        # Advance renderer - it never stops, it's relentless
        self.cycle += 1

        if self.cycle >= 341:
            self.cycle = 0
            self.scanline += 1

            if self.scanline >= 261:
                self.scanline = -1
                self.frame_complete = True

        if self.enable_log:
            print("Debug: ", end="")

            print(hex(self.bg_shifter_pattern_lo), " ", end="")
            print(hex(self.bg_shifter_pattern_hi), " ", end="")
            print(hex(self.bg_shifter_attrib_lo) , " ", end="")
            print(hex(self.bg_shifter_attrib_hi) , " ", end="")

            print(hex(self.bg_next_tile_id), " ", end="")
            print(hex(self.bg_next_tile_attrib), " ", end="")
            print(hex(self.bg_next_tile_lsb) , " ", end="")
            print(hex(self.bg_next_tile_msb) , " ", end="")

            print(hex(self.status.reg), " ", end="")
            print(hex(self.mask.reg), " ", end="")
            print(hex(self.control.reg) , " ", end="")
            print(hex(self.vram_addr.reg) , " ", end="")
            print(hex(self.tram_addr.reg), " ", end="")


            print(hex(self.fine_x), " ", end="")
            print(hex(self.address_latch), " ", end="")
            print(hex(self.ppu_data_buffer) , " ", end="")
            print(hex(self.scanline) , " ", end="")
            print(hex(self.cycle), " ")
Пример #6
0
    def get_colour_from_palette_ram(self, palette, pixel):

        value = to_8_bits(self.ppu_read(0x3F00 + (palette << 2) + pixel))

        return self.pal_screen[value & 0x3F]