diff --git a/src/sdl_render.c b/src/sdl_render.c index d76a3c1..d510ec3 100644 --- a/src/sdl_render.c +++ b/src/sdl_render.c @@ -150,10 +150,12 @@ static void sdl_render_done(nes_Renderer* rend) { } typedef enum { - Render_Mode_Sprite = 0b000, - Render_Mode_Background = 0b001, - Render_Mode_Behind = 0b010, - Render_Mode_Collide = 0b100, + Render_Mode_Sprite = 0b00000, + Render_Mode_Background = 0b00001, + Render_Mode_Behind = 0b00010, + Render_Mode_Collide = 0b00100, + Render_Mode_Flip_X = 0b01000, + Render_Mode_Flip_Y = 0b10000, } Render_Mode; @@ -165,13 +167,23 @@ static int render_sprite(nes_ppu* ppu, int index, uint8_t* sprite = &ppu->chr_mem[index * 16U]; uint8_t* dst_line = (uint8_t*)loc; const uint8_t* back_line = (uint8_t*)back_loc; + if (mode & Render_Mode_Flip_X) { + dst_line += 7; + back_line += 7; + } + if (mode & Render_Mode_Flip_Y) { + dst_line += (7 * pitch); + back_line += (7 * back_pitch); + } + for (int y = 8; y > 0; --y) { uint8_t lo = sprite[0U]; uint8_t hi = sprite[8U]; uint8_t* dst = dst_line; const uint8_t* back = back_line; for (int x = 8; x > 0; --x) { - int pal_idx = ((hi & 0x80) >> 6) | ((lo & 0x80) >> 7); + int pal_idx = ( ((hi & 0x80) >> 6) | + ((lo & 0x80) >> 7)); int nes_pal_idx = (pal_idx ? pal[pal_idx] : 0xFFU); if ( hit_pos < 0 && (ppu->mask & ppu_Mask_Back) && @@ -183,13 +195,24 @@ static int render_sprite(nes_ppu* ppu, int index, if ((mode & Render_Mode_Behind) && *back != 0xFFU) { nes_pal_idx = 0xFFU; } - *dst++ = nes_pal_idx; - ++back; + *dst = nes_pal_idx; + if (mode & Render_Mode_Flip_X) { + dst--; + back--; + } else { + dst++; + back++; + } hi <<= 1; lo <<= 1; } - dst_line += pitch; - back_line += back_pitch; + if (mode & Render_Mode_Flip_Y) { + dst_line -= pitch; + back_line -= back_pitch; + } else { + dst_line += pitch; + back_line += back_pitch; + } ++sprite; } return hit_pos; @@ -273,13 +296,18 @@ static void render_sprites(nes_ppu* ppu, const uint8_t* dst_back = back_offset + back_origin; // TODO: Support 8x16 sprites int index = bank + sprite->index; - // TODO: Support mirroring int pal_idx = (sprite->attr & oam_Attr_Pal_Mask); const uint8_t* pal = &ppu->palette[16 + (pal_idx * 4)]; Render_Mode mode = (sprite->attr & oam_Attr_Background) ? Render_Mode_Behind : Render_Mode_Sprite; if (i_sprite == 0) mode |= Render_Mode_Collide; + if (sprite->attr & oam_Attr_Flip_X) { + mode |= Render_Mode_Flip_X; + } + if (sprite->attr & oam_Attr_Flip_Y) { + mode |= Render_Mode_Flip_Y; + } int hit_pos = render_sprite(ppu, index, pal, mode, dst, pitch, dst_back, back_pitch);