1use crate::ppu; 2use crate::ppu::Ppu; 3use crate::ppu::registers::{BgMode, BitsPerPixel, Registers, TileSize}; 4use jgenesis_common::frontend::Color; 5use jgenesis_common::num::GetBit; 6 7impl Ppu { 8 pub fn copy_cgram(&self, out: &mut [Color]) { 9 for (out_color, &cgram_color) in out.iter_mut().zip(self.cgram.as_ref()) { 10 *out_color = ppu::convert_snes_color(cgram_color, ppu::MAX_BRIGHTNESS); 11 } 12 } 13 14 #[allow(clippy::needless_range_loop)] 15 pub fn copy_vram_2bpp(&self, out: &mut [Color], palette: u8, row_len: usize) { 16 let mut registers = Registers::new(); 17 registers.bg_mode = BgMode::One; 18 registers.bg_tile_size[0] = TileSize::Small; 19 registers.bg_tile_base_address[0] = 0; 20 21 for tile_number in 0..4096 { 22 let tile = ppu::get_bg_tile( 23 &self.vram, 24 ®isters, 25 0, 26 0, 27 0, 28 BitsPerPixel::Two, 29 tile_number as u16, 30 false, 31 false, 32 ); 33 let out_tile_idx = tile_number / row_len * row_len * 64 + (tile_number % row_len) * 8; 34 35 for row in 0..8 { 36 for col in 0..8 { 37 let out_idx = out_tile_idx + row * row_len * 8 + col; 38 39 let col_idx = 7 - col as u8; 40 let mut snes_color = 0; 41 snes_color |= u8::from(tile[row].bit(col_idx)); 42 snes_color |= u8::from(tile[row].bit(col_idx + 8)) << 1; 43 44 let cgram_idx = (palette << 2) | snes_color; 45 let color = if snes_color != 0 { self.cgram[cgram_idx as usize] } else { 0 }; 46 out[out_idx] = ppu::convert_snes_color(color, ppu::MAX_BRIGHTNESS); 47 } 48 } 49 } 50 } 51 52 pub fn copy_vram_4bpp(&self, out: &mut [Color], palette: u8, row_len: usize) { 53 let mut registers = Registers::new(); 54 registers.bg_mode = BgMode::One; 55 registers.bg_tile_size[0] = TileSize::Small; 56 registers.bg_tile_base_address[0] = 0; 57 58 for tile_number in 0..2048 { 59 let tile = ppu::get_bg_tile( 60 &self.vram, 61 ®isters, 62 0, 63 0, 64 0, 65 BitsPerPixel::Four, 66 tile_number as u16, 67 false, 68 false, 69 ); 70 let out_tile_idx = tile_number / row_len * row_len * 64 + (tile_number % row_len) * 8; 71 72 for row in 0..8 { 73 for col in 0..8 { 74 let out_idx = out_tile_idx + row * row_len * 8 + col; 75 76 let col_idx = 7 - col as u8; 77 let mut snes_color = 0; 78 snes_color |= u8::from(tile[row].bit(col_idx)); 79 snes_color |= u8::from(tile[row].bit(col_idx + 8)) << 1; 80 snes_color |= u8::from(tile[row + 8].bit(col_idx)) << 2; 81 snes_color |= u8::from(tile[row + 8].bit(col_idx + 8)) << 3; 82 83 let cgram_idx = (palette << 4) | snes_color; 84 let color = if snes_color != 0 { self.cgram[cgram_idx as usize] } else { 0 }; 85 out[out_idx] = ppu::convert_snes_color(color, ppu::MAX_BRIGHTNESS); 86 } 87 } 88 } 89 } 90 91 pub fn copy_vram_8bpp(&self, out: &mut [Color], row_len: usize) { 92 let mut registers = Registers::new(); 93 registers.bg_mode = BgMode::One; 94 registers.bg_tile_size[0] = TileSize::Small; 95 registers.bg_tile_base_address[0] = 0; 96 97 for tile_number in 0..1024 { 98 let tile = ppu::get_bg_tile( 99 &self.vram, 100 ®isters, 101 0, 102 0, 103 0, 104 BitsPerPixel::Eight, 105 tile_number as u16, 106 false, 107 false, 108 ); 109 let out_tile_idx = tile_number / row_len * row_len * 64 + (tile_number % row_len) * 8; 110 111 for row in 0..8 { 112 for col in 0..8 { 113 let out_idx = out_tile_idx + row * row_len * 8 + col; 114 115 let col_idx = 7 - col as u8; 116 let mut snes_color = 0; 117 snes_color |= u8::from(tile[row].bit(col_idx)); 118 snes_color |= u8::from(tile[row].bit(col_idx + 8)) << 1; 119 snes_color |= u8::from(tile[row + 8].bit(col_idx)) << 2; 120 snes_color |= u8::from(tile[row + 8].bit(col_idx + 8)) << 3; 121 snes_color |= u8::from(tile[row + 16].bit(col_idx)) << 4; 122 snes_color |= u8::from(tile[row + 16].bit(col_idx + 8)) << 5; 123 snes_color |= u8::from(tile[row + 24].bit(col_idx)) << 6; 124 snes_color |= u8::from(tile[row + 24].bit(col_idx + 8)) << 7; 125 126 let color = self.cgram[snes_color as usize]; 127 out[out_idx] = ppu::convert_snes_color(color, ppu::MAX_BRIGHTNESS); 128 } 129 } 130 } 131 } 132 133 pub fn copy_vram_mode7(&self, out: &mut [Color], row_len: usize) { 134 for tile_number in 0..256 { 135 let out_tile_idx = tile_number / row_len * row_len * 64 + (tile_number % row_len) * 8; 136 137 for row in 0..8 { 138 for col in 0..8 { 139 let out_idx = out_tile_idx + row * row_len * 8 + col; 140 141 let vram_addr = tile_number * 64 + row * 8 + col; 142 let snes_color = self.vram[vram_addr] >> 8; 143 let color = self.cgram[snes_color as usize]; 144 out[out_idx] = ppu::convert_snes_color(color, ppu::MAX_BRIGHTNESS); 145 } 146 } 147 } 148 } 149}