1+ mod sprite;
2+
13use crate :: cpu:: Cpu ;
24use crate :: memory:: Memory ;
35use crate :: nes_rom:: NesRom ;
46use crate :: ppu:: ppu_memory:: PpuMemory ;
5- use crate :: ppu:: Ppu ;
7+ use crate :: ppu:: { Ppu , OAM_SIZE } ;
8+ use crate :: render:: sprite:: Sprite ;
69use macroquad:: color:: { Color , BLACK , BLUE , RED , WHITE } ;
710use macroquad:: prelude:: { draw_rectangle, next_frame, request_new_screen_size} ;
811
12+ const SCREEN_WIDTH : u16 = 256 ;
13+ const SCREEN_HEIGHT : u16 = 240 ;
14+
915const RENDER_SCALE : f32 = 4. ;
1016const TILE_SIZE : f32 = RENDER_SCALE * 8. ;
1117
@@ -21,10 +27,10 @@ const SYSTEM_PALLETE: [u32; 64] = [
2127] ;
2228
2329pub fn get_color ( idx : u8 ) -> Color {
24- Color :: from_hex ( SYSTEM_PALLETE [ idx as usize ] )
30+ Color :: from_hex ( SYSTEM_PALLETE [ idx as usize % 64 ] )
2531}
2632
27- pub fn get_palette ( ppu : & Ppu < PpuMemory > , palette_idx : u16 ) -> [ Color ; 4 ] {
33+ pub fn get_bg_palette ( ppu : & Ppu < PpuMemory > , palette_idx : u16 ) -> [ Color ; 4 ] {
2834 [
2935 get_color ( ppu. memory . palette_table . read ( 0 ) ) ,
3036 get_color ( ppu. memory . palette_table . read ( palette_idx * 4 + 1 ) ) ,
@@ -33,15 +39,27 @@ pub fn get_palette(ppu: &Ppu<PpuMemory>, palette_idx: u16) -> [Color; 4] {
3339 ]
3440}
3541
42+ pub fn get_sprite_palette ( ppu : & Ppu < PpuMemory > , palette_idx : u16 ) -> [ Color ; 4 ] {
43+ get_bg_palette ( ppu, palette_idx + 4 )
44+ }
45+
3646pub async fn render_frame ( cpu : & mut Cpu ) {
3747 let ppu = & mut cpu. bus . ppu ;
38- let bank = ppu. background_pattern_addr ( ) ;
3948
4049 request_new_screen_size (
4150 RENDER_SCALE * ( 8 * 32 ) as f32 ,
4251 RENDER_SCALE * ( 8 * 30 ) as f32 ,
4352 ) ;
4453
54+ render_background ( ppu) . await ;
55+ render_sprites ( ppu) . await ;
56+
57+ next_frame ( ) . await
58+ }
59+
60+ async fn render_background ( ppu : & mut Ppu < PpuMemory > ) {
61+ let bank = ppu. background_pattern_addr ( ) ;
62+
4563 fn calc_screen_pos ( tile_index : usize , pixel_index : usize ) -> ( f32 , f32 ) {
4664 let tile_x = ( tile_index % 32 ) as f32 ;
4765 let tile_y = ( tile_index / 32 ) as f32 ;
@@ -59,7 +77,7 @@ pub async fn render_frame(cpu: &mut Cpu) {
5977 // which tile are we rendering?
6078 let tile = ppu. memory . read ( nametable_addr + tile_index) as u16 ;
6179 let chr_data = ppu. memory . chr_rom
62- [ ( bank + tile * 16 ) as usize ..= ( bank + tile * 16 + 15 ) as usize ]
80+ [ ( bank + tile * 16 ) as usize ..( bank + tile * 16 + 16 ) as usize ]
6381 . to_vec ( ) ;
6482 let pixels = chr_data_to_pixels ( chr_data) ;
6583
@@ -75,7 +93,7 @@ pub async fn render_frame(cpu: &mut Cpu) {
7593 ( 1 , 1 ) => ( meta_palette >> 6 ) & 0b11 ,
7694 _ => panic ! ( "unexpected tile position" ) ,
7795 } ;
78- let colors = get_palette ( ppu, palette_idx) ;
96+ let colors = get_bg_palette ( ppu, palette_idx) ;
7997
8098 for i in 0 ..pixels. len ( ) {
8199 let ( screen_x, screen_y) = calc_screen_pos ( tile_index as usize , i) ;
@@ -88,7 +106,48 @@ pub async fn render_frame(cpu: &mut Cpu) {
88106 )
89107 }
90108 }
91- next_frame ( ) . await
109+ }
110+
111+ async fn render_sprites ( ppu : & Ppu < PpuMemory > ) {
112+ for oam_idx in ( 0 ..OAM_SIZE ) . step_by ( 4 ) . rev ( ) {
113+ let sprite = Sprite :: from_data ( & ppu. oam [ oam_idx..oam_idx + 4 ] ) ;
114+ if !sprite. visible {
115+ continue ;
116+ }
117+ let bank = ppu. sprite_pattern_addr ( ) ;
118+ let tile = sprite. tile_index as u16 ;
119+ let chr_data = ppu. memory . chr_rom
120+ [ ( bank + tile * 16 ) as usize ..( bank + tile * 16 + 16 ) as usize ]
121+ . to_vec ( ) ;
122+ let pixels = chr_data_to_pixels ( chr_data) ;
123+
124+ let colors = get_sprite_palette ( ppu, sprite. palette as u16 ) ;
125+
126+ for x in 0 ..8 {
127+ for y in 0 ..8 {
128+ let pixel_idx = ( y * 8 + x) as usize ;
129+ if pixels[ pixel_idx] == 0 {
130+ continue ;
131+ }
132+
133+ let x = if sprite. flip_horizontally { 7 - x } else { x } ;
134+ let y = if sprite. flip_vertically { 7 - y } else { y } ;
135+
136+ if sprite. x as u16 + x > SCREEN_WIDTH || sprite. y as u16 + y > SCREEN_HEIGHT {
137+ continue ;
138+ }
139+ let ( screen_x, screen_y) = ( sprite. x as u16 + x, sprite. y as u16 + y) ;
140+
141+ draw_rectangle (
142+ screen_x as f32 * RENDER_SCALE ,
143+ screen_y as f32 * RENDER_SCALE ,
144+ RENDER_SCALE ,
145+ RENDER_SCALE ,
146+ colors[ pixels[ pixel_idx] as usize ] ,
147+ )
148+ }
149+ }
150+ }
92151}
93152
94153pub async fn debug_chr_rom ( rom : & NesRom ) {
0 commit comments