def render_background(self, line: int): line_width = (Window.SCREEN_HEIGHT - line - 1) * Window.SCREEN_WIDTH if self.lcdControlRegister.bg_window_display_priority(): # tile and map select tiles_select = self.lcdControlRegister.bg_and_window_tile_data_select( ) map_select = self.lcdControlRegister.bg_tile_map_display_select() # x pixel offset scx = self.mmu.read_byte(IO_Registers.SCX) # y pixel offset scy = self.mmu.read_byte(IO_Registers.SCY) # line with y offset line_adjusted = (line + scy) & 0xff # get position of tile row to read y_offset = int(line_adjusted / 8) * 32 # relative line number in tile tile_line = line_adjusted % 8 # relative line number offset tile_line_offset = tile_line * 2 palette = self.mmu.read_byte(IO_Registers.BGP) x = 0 while x < 32: tile = 0 if tiles_select == 0x8800: tile = signed_value( self.mmu.read_byte(map_select + y_offset + x)) tile += 128 else: tile = self.mmu.read_byte(map_select + y_offset + x) line_pixel_offset = x * 8 tile_select_offset = tile * 16 tile_address = tiles_select + tile_select_offset + tile_line_offset byte_1 = self.mmu.read_byte(tile_address) byte_2 = self.mmu.read_byte(tile_address + 1) pixelx = 0 buffer_addr = (line_pixel_offset - scx) while pixelx < 8: buffer_addr = buffer_addr & 0xff shift = 0x1 << (7 - pixelx) pixel = 1 if (byte_1 & shift > 0) else 0 pixel |= 2 if (byte_2 & shift > 0) else 0 color = (palette >> (pixel * 2)) & 0x3 pixelx += 1 if 0 <= buffer_addr < Window.SCREEN_WIDTH: position = line_width + buffer_addr self.framebuffer[position] = self.rgb(color) buffer_addr = (line_pixel_offset + pixelx - scx) x += 1 else: for i in range(0, Window.SCREEN_WIDTH): self.framebuffer[line_width + i] = self.rgb(0)
def render_window(cls, line : int): line_width = (Window.SCREEN_HEIGHT - line -1) * Window.SCREEN_WIDTH # dont render if the window is outside the bounds of the screen or # if the LCDC window enable bit flag is not set if cls.window_line > 143 or not LCDControlRegister.window_display_enable(cls.lcdc): return window_pos_x = cls.wx - 7 window_pos_y = cls.wy # don't render if the window is outside the bounds of the screen if window_pos_x > 159 or window_pos_y > 143 or window_pos_y > line: return tiles_select = LCDControlRegister.bg_and_window_tile_data_select(cls.lcdc) map_select = LCDControlRegister.window_tile_map_display_select(cls.lcdc) line_adjusted = cls.window_line y_offset = (line_adjusted // 8) * 32 tile_line = line_adjusted % 8 tile_line_offset = tile_line * 2 for x in range(32): tile = 0 if tiles_select == 0x800: tile = signed_value(cls.vram[0][map_select + y_offset + x]) tile += 128 else: tile = cls.vram[0][map_select + y_offset + x] line_pixel_offset = x * 8 tile_select_offset = tile * 16 tile_address = tiles_select + tile_select_offset + tile_line_offset tile_attributes = TileAttributes(cls.vram[1][map_select + y_offset + x]) if not cls.cgb_mode: byte_1 = cls.vram[0][tile_address] byte_2 = cls.vram[0][tile_address + 1] else: if tile_attributes.is_vertical_flip(): tile_address = tile_address - tile_line_offset + ( 7 - tile_line ) * 2 byte_1 = cls.vram[tile_attributes.get_vram_bank()][tile_address] byte_2 = cls.vram[tile_attributes.get_vram_bank()][tile_address + 1] if tile_attributes.is_horizontal_flip(): byte_1 = flip_byte(byte_1) byte_2 = flip_byte(byte_2) for pixelx in range(8): buffer_addr = line_pixel_offset + pixelx + window_pos_x if buffer_addr < 0 or buffer_addr >= Window.SCREEN_WIDTH: continue shift = 0x1 << (7 - pixelx) pixel = 0 if (byte_1 & shift == shift) and (byte_2 & shift == shift): pixel = 3 elif (byte_1 & shift == 0x0) and (byte_2 & shift == shift): pixel = 2 elif (byte_1 & shift == shift) and (byte_2 & shift == 0x0): pixel = 1 elif (byte_1 & shift == 0x0) and (byte_2 & shift == 0x00): pixel = 0 position = line_width + buffer_addr color = (cls.bgp >> (pixel * 2)) & 0x3 if not cls.cgb_mode: Window.framebuffer[position] = cls.rgb(color) cls.original_color[position] = color else: if cls.mmu.bootstrap_enabled or cls.mmu.rom.is_cgb(): color = pixel Window.framebuffer[position] = cls.mmu.cgb_palette.get_bg_rgba_palette_color(tile_attributes.get_palette(), color) cls.bg_priority[position] = tile_attributes.is_bg_priority() cls.original_color[position] = color cls.window_line += 1
def render_background(cls, line : int): line_width = (Window.SCREEN_HEIGHT - line -1) * Window.SCREEN_WIDTH if LCDControlRegister.bg_window_display_priority(cls.lcdc): # tile and map select tiles_select = LCDControlRegister.bg_and_window_tile_data_select(cls.lcdc) map_select = LCDControlRegister.bg_tile_map_display_select(cls.lcdc) # line with y offset line_adjusted = (line + cls.scy) & 0xff # get position of tile row to read y_offset = (line_adjusted // 8) * 32 # relative line number in tile tile_line = line_adjusted % 8 # relative line number offset tile_line_offset = tile_line * 2 x = 0 while x < 32: tile = 0 if tiles_select == 0x800: tile = signed_value(cls.vram[0][map_select + y_offset + x]) tile += 128 else: tile = cls.vram[0][map_select + y_offset + x] line_pixel_offset = x * 8 tile_select_offset = tile * 16 tile_address = tiles_select + tile_select_offset + tile_line_offset if not cls.cgb_mode: byte_1 = cls.vram[0][tile_address] byte_2 = cls.vram[0][tile_address + 1] else: tile_attributes = TileAttributes(cls.vram[0][map_select + y_offset + x]) if tile_attributes.is_vertical_flip(): tile_address = tile_address - tile_line_offset + ( 7 - tile_line ) * 2 byte_1 = cls.vram[tile_attributes.get_vram_bank()][tile_address] byte_2 = cls.vram[tile_attributes.get_vram_bank()][tile_address + 1] if tile_attributes.is_horizontal_flip(): byte_1 = flip_byte(byte_1) byte_2 = flip_byte(byte_2) pixelx = 0 buffer_addr = (line_pixel_offset - cls.scx) while pixelx < 8: shift = 0x1 << (7 - pixelx) pixelx += 1 buffer_addr &= 0xff if 0 <= buffer_addr < Window.SCREEN_WIDTH: pixel = 1 if (byte_1 & shift > 0) else 0 pixel |= 2 if (byte_2 & shift > 0) else 0 color = (cls.bgp >> (pixel * 2)) & 0x3 position = line_width + buffer_addr % Window.SCREEN_WIDTH cls.original_color[position] = color if not cls.cgb_mode: Window.framebuffer[position] = cls.rgb(color) else: """ if cls.mmu.bootstrap_enabled or cls.mmu.rom.is_cgb(): color = pixel """ #Window.framebuffer[position] = cls.mmu.cgb_palette.get_bg_rgba_palette_color(tile_attributes.get_palette(), color) Window.framebuffer[position] = cls.rgb(color) #FIXME cls.bg_priority[position] = tile_attributes.is_bg_priority() buffer_addr = ( line_pixel_offset + pixelx - cls.scx ) x += 1 else: for i in range(0, Window.SCREEN_WIDTH): Window.framebuffer[line_width + i] = cls.rgb(0) cls.original_color[line_width + i] = 0
def render_window(self, line: int): line_width = (Window.SCREEN_HEIGHT - line - 1) * Window.SCREEN_WIDTH # dont render if the window is outside the bounds of the screen or # if the LCDC window enable bit flag is not set if self.window_line > 143 or not self.lcdControlRegister.window_display_enable( ): return window_pos_x = self.mmu.read_byte(IO_Registers.WX) - 7 window_pos_y = self.mmu.read_byte(IO_Registers.WY) # don't render if the window is outside the bounds of the screen if window_pos_x > 159 or window_pos_y > 143 or window_pos_y > line: return tiles_select = self.lcdControlRegister.bg_and_window_tile_data_select() map_select = self.lcdControlRegister.window_tile_map_display_select() line_adjusted = self.window_line y_offset = int(line_adjusted / 8) * 32 tile_line = line_adjusted % 8 tile_line_offset = tile_line * 2 for x in range(32): tile = 0 if tiles_select == 0x8800: tile = signed_value( self.mmu.vram.read_value(map_select + y_offset + x, 0)) tile += 128 else: tile = self.mmu.vram.read_value(map_select + y_offset + x, 0) line_pixel_offset = x * 8 tile_select_offset = tile * 16 tile_address = tiles_select + tile_select_offset + tile_line_offset tile_attributes = TileAttributes( self.mmu.vram.read_value(map_select + y_offset + x, 1)) if not self.cgb_mode: byte_1 = self.mmu.read_byte(tile_address) byte_2 = self.mmu.read_byte(tile_address + 1) else: if tile_attributes.is_vertical_flip(): tile_address = tile_address - tile_line_offset + ( 7 - tile_line) * 2 byte_1 = self.mmu.vram.read_value( tile_address, tile_attributes.get_vram_bank()) byte_2 = self.mmu.vram.read_value( tile_address + 1, tile_attributes.get_vram_bank()) if tile_attributes.is_horizontal_flip(): byte_1 = flip_byte(byte_1) byte_2 = flip_byte(byte_2) palette = self.mmu.read_byte(IO_Registers.BGP) for pixelx in range(8): buffer_addr = line_pixel_offset + pixelx + window_pos_x if buffer_addr < 0 or buffer_addr >= Window.SCREEN_WIDTH: continue shift = 0x1 << (7 - pixelx) pixel = 0 if (byte_1 & shift == shift) and (byte_2 & shift == shift): pixel = 3 elif (byte_1 & shift == 0x0) and (byte_2 & shift == shift): pixel = 2 elif (byte_1 & shift == shift) and (byte_2 & shift == 0x0): pixel = 1 elif (byte_1 & shift == 0x0) and (byte_2 & shift == 0x00): pixel = 0 position = line_width + buffer_addr color = (palette >> (pixel * 2)) & 0x3 if not self.cgb_mode: self.framebuffer[position] = self.rgb(color) self.original_color[position] = color else: if self.mmu.bootstrap_enabled or self.mmu.rom.is_cgb(): color = pixel self.framebuffer[ position] = self.mmu.cgb_palette.get_bg_rgba_palette_color( tile_attributes.get_palette(), color) self.bg_priority[ position] = tile_attributes.is_bg_priority() self.original_color[position] = color self.window_line += 1
def render_background(self, line: int): line_width = (Window.SCREEN_HEIGHT - line - 1) * Window.SCREEN_WIDTH if self.lcdControlRegister.bg_window_display_priority(): # tile and map select tiles_select = self.lcdControlRegister.bg_and_window_tile_data_select( ) map_select = self.lcdControlRegister.bg_tile_map_display_select() # x pixel offset scx = self.mmu.read_byte(IO_Registers.SCX) # y pixel offset scy = self.mmu.read_byte(IO_Registers.SCY) # line with y offset line_adjusted = (line + scy) & 0xff # get position of tile row to read y_offset = int(line_adjusted / 8) * 32 # relative line number in tile tile_line = line_adjusted % 8 # relative line number offset tile_line_offset = tile_line * 2 palette = self.mmu.read_byte(IO_Registers.BGP) x = 0 while x < 32: tile = 0 if tiles_select == 0x8800: tile = signed_value( self.mmu.vram.read_value(map_select + y_offset + x, 0)) tile += 128 else: tile = self.mmu.vram.read_value(map_select + y_offset + x, 0) line_pixel_offset = x * 8 tile_select_offset = tile * 16 tile_address = tiles_select + tile_select_offset + tile_line_offset tile_attributes = TileAttributes( self.mmu.vram.read_value(map_select + y_offset + x, 1)) if not self.cgb_mode: byte_1 = self.mmu.read_byte(tile_address) byte_2 = self.mmu.read_byte(tile_address + 1) else: if tile_attributes.is_vertical_flip(): tile_address = tile_address - tile_line_offset + ( 7 - tile_line) * 2 byte_1 = self.mmu.vram.read_value( tile_address, tile_attributes.get_vram_bank()) byte_2 = self.mmu.vram.read_value( tile_address + 1, tile_attributes.get_vram_bank()) if tile_attributes.is_horizontal_flip(): byte_1 = flip_byte(byte_1) byte_2 = flip_byte(byte_2) pixelx = 0 buffer_addr = (line_pixel_offset - scx) while pixelx < 8: shift = 0x1 << (7 - pixelx) pixelx += 1 buffer_addr &= 0xff if 0 <= buffer_addr < Window.SCREEN_WIDTH: pixel = 1 if (byte_1 & shift > 0) else 0 pixel |= 2 if (byte_2 & shift > 0) else 0 color = (palette >> (pixel * 2)) & 0x3 position = line_width + buffer_addr % Window.SCREEN_WIDTH self.original_color[position] = color if not self.cgb_mode: self.framebuffer[position] = self.rgb(color) else: if self.mmu.bootstrap_enabled or self.mmu.rom.is_cgb( ): color = pixel self.framebuffer[ position] = self.mmu.cgb_palette.get_bg_rgba_palette_color( tile_attributes.get_palette(), color) self.bg_priority[ position] = tile_attributes.is_bg_priority() buffer_addr = (line_pixel_offset + pixelx - scx) x += 1 else: for i in range(0, Window.SCREEN_WIDTH): self.framebuffer[line_width + i] = self.rgb(0) self.original_color[line_width + i] = 0
def render_window(self, line: int): line_width = (Window.SCREEN_HEIGHT - line - 1) * Window.SCREEN_WIDTH # dont render if the window is outside the bounds of the screen or # if the LCDC window enable bit flag is not set if self.window_line > 143 or not self.lcdControlRegister.window_display_enable( ): return window_pos_x = self.mmu.read_byte(IO_Registers.WX) - 7 window_pos_y = self.mmu.read_byte(IO_Registers.WY) # don't render if the window is outside the bounds of the screen if window_pos_x > 159 or window_pos_y > 143 or window_pos_y > line: return tiles_select = self.lcdControlRegister.bg_and_window_tile_data_select() map_select = self.lcdControlRegister.window_tile_map_display_select() line_adjusted = self.window_line y_offset = int(line_adjusted / 8) * 32 tile_line = line_adjusted % 8 tile_line_offset = tile_line * 2 for x in range(0, 32): tile = 0 if tiles_select == 0x8800: tile = signed_value( self.mmu.read_byte(map_select + y_offset + x)) tile += 128 else: tile = self.mmu.read_byte(map_select + y_offset + x) line_pixel_offset = x * 8 tile_select_offset = tile * 16 tile_address = tiles_select + tile_select_offset + tile_line_offset byte_1 = self.mmu.read_byte(tile_address) byte_2 = self.mmu.read_byte(tile_address + 1) palette = self.mmu.read_byte(IO_Registers.BGP) for pixelx in range(0, 8): buffer_addr = line_pixel_offset + pixelx + window_pos_x if buffer_addr < 0 or buffer_addr >= Window.SCREEN_WIDTH: continue shift = 0x1 << (7 - pixelx) pixel = 0 if (byte_1 & shift == shift) and (byte_2 & shift == shift): pixel = 3 elif (byte_1 & shift == 0x0) and (byte_2 & shift == shift): pixel = 2 elif (byte_1 & shift == shift) and (byte_2 & shift == 0x0): pixel = 1 elif (byte_1 & shift == 0x0) and (byte_2 & shift == 0x00): pixel = 0 position = line_width + buffer_addr color = (palette >> (pixel * 2)) & 0x3 self.framebuffer[position] = self.rgb(color) self.window_line += 1