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]
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)
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
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
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), " ")
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]