| @@ -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); | |||