@@ -185,9 +185,10 @@ void set_pixel(size_t x, size_t y, uint8_t palette_color) {
185185 size_t index = (y * SCREEN_WIDTH + x ) * 3 ;
186186
187187 if (index < SCREEN_WIDTH * SCREEN_HEIGHT * 3 ) {
188- uint8_t r = COLOR_PALETTE [palette_color * 3 ];
189- uint8_t g = COLOR_PALETTE [palette_color * 3 + 1 ];
190- uint8_t b = COLOR_PALETTE [palette_color * 3 + 2 ];
188+ size_t palette_offset = palette_color * 3 ;
189+ uint8_t r = COLOR_PALETTE [palette_offset ];
190+ uint8_t g = COLOR_PALETTE [palette_offset + 1 ];
191+ uint8_t b = COLOR_PALETTE [palette_offset + 2 ];
191192
192193 frame [index ] = r ;
193194 frame [index + 1 ] = g ;
@@ -199,8 +200,8 @@ size_t get_background_palette_index(size_t tile_col, size_t tile_row, size_t nam
199200 size_t attr_table_index = (tile_row / 4 ) * 8 + (tile_col / 4 );
200201 // the attribute table is stored after the nametable (960 bytes)
201202 size_t attr_table_byte = nametable [nametable_offset + 960 + attr_table_index ];
202- size_t block_x = (tile_col % 4 ) / 2 ;
203- size_t block_y = (tile_row % 4 ) / 2 ;
203+ size_t block_x = (tile_col & 3 ) / 2 ;
204+ size_t block_y = (tile_row & 3 ) / 2 ;
204205 size_t shift = block_y * 4 + block_x * 2 ;
205206
206207 return ((attr_table_byte >> shift ) & 0b11 ) * BYTES_PER_PALETTE ;
@@ -224,7 +225,7 @@ Tile* get_cached_background_tile(size_t n, size_t bank_offset, size_t palette_of
224225 uint8_t plane1 = chr_rom [bank_offset + n * 16 + tile_y ];
225226 uint8_t plane2 = chr_rom [bank_offset + n * 16 + tile_y + 8 ];
226227
227- for (size_t tile_x = 0 ; tile_x < 8 ; tile_x ++ ) {
228+ for (int tile_x = 7 ; tile_x >= 0 ; tile_x -- ) {
228229 uint8_t bit0 = plane1 & 1 ;
229230 uint8_t bit1 = plane2 & 1 ;
230231 uint8_t color_index = (uint8_t )((bit1 << 1 ) | bit0 );
@@ -248,7 +249,7 @@ Tile* get_cached_background_tile(size_t n, size_t bank_offset, size_t palette_of
248249 uint8_t g = COLOR_PALETTE [palette_offset + 1 ];
249250 uint8_t b = COLOR_PALETTE [palette_offset + 2 ];
250251
251- size_t tile_offset = ( tile_y * 8 + tile_x ) ;
252+ size_t tile_offset = tile_y * 8 + ( size_t ) tile_x ;
252253 size_t tile_offset_times_3 = tile_offset * 3 ;
253254
254255 tile -> pixels [tile_offset_times_3 ] = r ;
@@ -282,53 +283,73 @@ void draw_background_tile(
282283
283284 Tile * tile = get_cached_background_tile (n , bank_offset , palette_idx );
284285
286+ // copy the tile, row by row
285287 for (size_t tile_y = 0 ; tile_y < 8 ; tile_y ++ ) {
286- for (size_t tile_x = 0 ; tile_x < 8 ; tile_x ++ ) {
287- size_t tile_offset = (tile_y * 8 + tile_x );
288- int nametable_x = (int )x + ((int )(7 - (int )tile_x ));
289-
290- if (nametable_x >= min_x && nametable_x < max_x ) {
291- size_t screen_x = (size_t )(shift_x + nametable_x );
292- size_t screen_y = y + tile_y ;
293-
294- memcpy (& frame [(screen_y * SCREEN_WIDTH + screen_x ) * 3 ], & tile -> pixels [tile_offset * 3 ], 3 );
295- opaque_bg_mask [screen_y * SCREEN_WIDTH + screen_x ] = tile -> opaque_mask [tile_offset ];
288+ int screen_x = (int )x + shift_x ;
289+ size_t screen_y = y + tile_y ;
290+
291+ if ((int )x >= min_x && (int )(x + 7 ) < max_x ) {
292+ size_t tile_offset = tile_y * 8 ;
293+ size_t frame_offset = screen_y * SCREEN_WIDTH + (size_t )screen_x ;
294+
295+ memcpy (& frame [frame_offset * 3 ], & tile -> pixels [tile_offset * 3 ], 8 * 3 );
296+ memcpy (& opaque_bg_mask [frame_offset ], & tile -> opaque_mask [tile_offset ], 8 );
297+ } else {
298+ // clipping
299+ for (size_t tile_x = 0 ; tile_x < 8 ; tile_x ++ ) {
300+ size_t tile_offset = tile_y * 8 + tile_x ;
301+ int nametable_x = (int )x + (int )tile_x ;
302+
303+ if (nametable_x >= min_x && nametable_x < max_x ) {
304+ size_t screen_x = (size_t )(shift_x + nametable_x );
305+ size_t frame_offset = screen_y * SCREEN_WIDTH + screen_x ;
306+
307+ memcpy (& frame [frame_offset * 3 ], & tile -> pixels [tile_offset * 3 ], 3 );
308+ opaque_bg_mask [frame_offset ] = tile -> opaque_mask [tile_offset ];
309+ }
296310 }
297311 }
298312 }
299313}
300314
301- bool show_status_bar () {
315+ inline bool show_status_bar () {
302316 return ram [Sprite0HitDetectFlag ];
303317}
304318
305319void render_status_bar (size_t bank_offset ) {
306- // the status bar spans the top 4 rows
307- for (size_t i = 0 ; i < 4 * TILES_PER_ROW ; i ++ ) {
308- uint8_t tile_x = i % TILES_PER_ROW ;
309- uint8_t tile_y = (uint8_t )(i / TILES_PER_ROW );
310- uint8_t tile = nametable [i ];
311- size_t palette_index = get_background_palette_index (tile_x , tile_y , 0 );
312-
313- draw_background_tile (tile , tile_x * 8 , tile_y * 8 , bank_offset , palette_index , 0 , 0 , SCREEN_WIDTH );
320+ for (size_t tile_y = 0 ; tile_y < 4 ; ++ tile_y ) {
321+ for (size_t tile_x = 0 ; tile_x < TILES_PER_ROW ; ++ tile_x ) {
322+ size_t i = tile_y * TILES_PER_ROW + tile_x ;
323+
324+ uint8_t tile = nametable [i ];
325+ size_t palette_index = get_background_palette_index (tile_x , tile_y , 0 );
326+
327+ size_t screen_x = tile_x * 8 ;
328+ size_t screen_y = tile_y * 8 ;
329+
330+ draw_background_tile (tile , screen_x , screen_y , bank_offset , palette_index , 0 , 0 , SCREEN_WIDTH );
331+ }
314332 }
315333}
316334
317335void render_nametable (size_t nametable_offset , size_t bank_offset , int shift_x , int min_x , int max_x , size_t min_tile_y ) {
318336 bool draw_leftmost_tile = ppu_mask & 0b10 ;
319337
320- for (size_t i = min_tile_y * TILES_PER_ROW ; i < TILES_PER_ROW * TILES_PER_COLUMN ; i ++ ) {
321- uint8_t tile_x = i % TILES_PER_ROW ;
322- uint8_t tile_y = (uint8_t )(i / TILES_PER_ROW );
338+ for (size_t tile_y = min_tile_y ; tile_y < TILES_PER_COLUMN ; ++ tile_y ) {
339+ for (size_t tile_x = 0 ; tile_x < TILES_PER_ROW ; ++ tile_x ) {
340+ if (!draw_leftmost_tile && tile_x == 0 ) {
341+ continue ;
342+ }
323343
324- if (! draw_leftmost_tile && tile_x == 0 ) {
325- continue ;
326- }
344+ size_t i = tile_y * TILES_PER_ROW + tile_x ;
345+ uint8_t tile = nametable [ nametable_offset + i ] ;
346+ size_t palette_index = get_background_palette_index ( tile_x , tile_y , nametable_offset );
327347
328- uint8_t tile = nametable [ nametable_offset + i ] ;
329- size_t palette_index = get_background_palette_index ( tile_x , tile_y , nametable_offset ) ;
348+ size_t screen_x = tile_x << 3 ;
349+ size_t screen_y = tile_y << 3 ;
330350
331- draw_background_tile (tile , tile_x * 8 , tile_y * 8 , bank_offset , palette_index , shift_x , min_x , max_x );
351+ draw_background_tile (tile , screen_x , screen_y , bank_offset , palette_index , shift_x , min_x , max_x );
352+ }
332353 }
333354}
334355
0 commit comments